Compare commits

...
Author SHA1 Message Date
cat e58b6eb171 internal/rosa/package: net-tools
These are nice to have, but will not be included in the base system.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-15 16:18:44 +09:00
cat 1625aaee80 internal/rosa/package/nss: 3.126 to 3.126.1
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-14 16:19:17 +09:00
cat 203ce6864b internal/rosa/package/go: 1.26.5 to 1.26.6
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-14 16:18:55 +09:00
cat 050051e593 internal/rosa/package/procps: 4.0.6 to 4.0.7
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-13 20:09:27 +09:00
cat 530b63ca70 internal/rosa/package/harfbuzz: 14.3.0 to 14.3.1
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-13 20:09:06 +09:00
cat 8821d34b10 internal/pkg: deduplicate unwrapped input errors
This avoids repeating errors belonging to multiple instances of the same artifact in different locations in memory.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-12 22:34:12 +09:00
cat 054a8813d7 internal/rosa/package/qemu: disable broken tests
The copy-before-write test was failing on a Haswell machine, although it seems to work pretty reliably on the Zen 3 workstation and RK3588.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-12 19:01:49 +09:00
cat 1bc16b51a6 cmd/hakurei: terminate specified instance
This is theoretically susceptible to the PID race, but such an event is statistically impossible, and not exploitable in the intended use case, regardless.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-12 18:03:54 +09:00
cat 3718c044c4 internal/rosa/package/qemu: use system meson
This also enables meson colour and fixes test suite invocation.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-12 17:57:57 +09:00
cat 07e92db918 internal/rosa/package/dbus: xdg-dbus-proxy 0.1.7 to 0.1.8
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-12 16:29:07 +09:00
cat d2ee7cb551 internal/rosa/package/qemu: 11.0.3 to 11.1.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-12 16:28:47 +09:00
cat 39e757a84d internal/rosa/package/python: wheel 0.47.0 to 0.48.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-12 16:28:18 +09:00
cat a431f16e6f internal/pkg: in-flight error resolution
The DCE is a slow and overcomplicated solution to a simple problem. This change replaces the DCE by resolving errors in-flight.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-12 16:21:47 +09:00
cat 1f45d44e7f internal/rosa/package/python: hatchling 1.17.1 to 1.18.0
This has gained another dependency, pulling in the fourth python build system we have had to package.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 21:43:19 +09:00
cat 92d01752ab internal/rosa/package/python: poetry-core tomlkit
This is the fourth python build system required to package meson. Required by tomlkit which is now required by hatchling (yet another build system).

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 21:42:09 +09:00
cat 82bf46d23f internal/rosa/package: replace pkg-config
This replaces pkg-config with pkgconf for most packages.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 21:27:09 +09:00
cat 2abcb99ea2 internal/rosa/package: pkgconf
This replaces pkg-config for packages later than meson.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 21:23:11 +09:00
cat 2218efc0cf internal/rosa: improve nil-exec error reporting
This panics with a more descriptive error instead of relying on the SIGSEGV handler.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 20:40:00 +09:00
cat 30c5525d7b internal/rosa/package/libpsl: 0.23.1 to 0.23.2
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 14:39:44 +09:00
cat bf6d1ada71 internal/rosa/package/libexpat: 2.8.2 to 2.8.3
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 14:39:16 +09:00
cat 16294a35ee internal/rosa/package/googletest: 1.17.0 to 1.18.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 14:38:56 +09:00
cat 22756af8fb internal/rosa/package/firmware: 20260622 to 20260810
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 14:38:36 +09:00
cat 739ae4a7cf internal/rosa/package/meson: 1.11.2 to 1.12.0
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 14:38:13 +09:00
cat eec89c4519 internal/rosa/package/kernel: 6.18.43 to 6.18.44
Typo fix of rkisp1_ext_param_buffer_version caused world rebuild.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-11 00:08:47 +09:00
cat 7193656b6a internal/rosa: improve helper bindings
This uses more intuitive names for some arguments and inverts their default value. Slices and nil-capable strings replace skip arguments.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-10 21:55:47 +09:00
cat 7d86e19c07 internal/rosa/azalea: implement nil identifier
This also implements a nil-capable string type.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-10 21:36:21 +09:00
cat f1ffb180bc internal/rosa: optionally block packages from early stages
This helps avoid inadvertently increasing bootstrap input count.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-10 17:50:36 +09:00
cat 7f690145e3 internal/rosa/package/hakurei: 0.4.5 to 0.4.6
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-09 21:21:39 +09:00
cat c79ae7aed6 release: 0.4.6
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-09 20:48:28 +09:00
cat 396ae2ba2a cmd/dist: replace readme with license
The readme document is pretty useless for anything other than the website, so replace it with something more relevant.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-09 20:40:52 +09:00
cat 1e85dca9e2 internal/rosa/package/python: setuptools 83.0.0 to 84.0.0
This has also turned into AI slop at some point, although its quality was never great to begin with. This may be a candidate to pin and ignore.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-09 19:13:05 +09:00
90 changed files with 916 additions and 578 deletions
+1 -1
View File
@@ -1 +1 @@
v0.4.5
v0.4.6
+6
View File
@@ -36,6 +36,11 @@ _hakurei_show() {
'files:files:__hakurei_files'
}
_hakurei_kill() {
_alternative \
'instances:domains:__hakurei_instances'
}
__hakurei_files() {
_files -g "*.(json|hakurei)"
return $?
@@ -60,6 +65,7 @@ __hakurei_instances() {
"run:Load and start container from configuration file"
"exec:Configure and start a permissive container"
"show:Show live or local instance configuration"
"kill:Terminate an active instance"
"ps:List active instances"
"version:Display version information"
"license:Show full license text"
+2 -2
View File
@@ -217,7 +217,7 @@ func main() {
mustWriteFile("comp/", nil, os.ModeDir|0755)
mustWriteFile("comp/_hakurei", comp, 0644)
mustWriteFile("install.sh", []byte(`#!/bin/sh -e
cd "$(dirname -- "$0")" || exit 1
cd "$(dirname -- "$0")"
install -vDm0755 "bin/hakurei" "${DESTDIR}`+prefix+`/bin/hakurei"
install -vDm0755 "bin/sharefs" "${DESTDIR}`+prefix+`/bin/sharefs"
@@ -230,7 +230,7 @@ fi
install -vDm0644 "comp/_hakurei" "${DESTDIR}`+prefix+`/share/zsh/site-functions/_hakurei"
`), 0755)
mustWriteFromPath("README.md", "README.md", 0)
mustWriteFromPath("LICENSE", "LICENSE", 0)
mustWriteFile("hsurc.default", []byte("1000 0"), 0400)
mustWriteFromPath("bin/hsu", filepath.Join(s, "hsu"), 04511)
for _, name := range []string{
+18
View File
@@ -11,6 +11,7 @@ import (
"os/user"
"strconv"
"sync"
"syscall"
"time"
"hakurei.app/check"
@@ -372,6 +373,23 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
Flag(&flagNoStore, "no-store", command.BoolFlag(false), "Do not attempt to match from active instances")
}
c.NewCommand("kill", "Terminate an active instance", func(args []string) error {
if len(args) != 1 {
log.Fatal("kill requires 1 argument")
}
var sc hst.Paths
env.CopyPaths().Copy(&sc, new(outcome.Hsu).MustID(nil))
entry := tryIdentifier(msg, args[0], outcome.NewStore(&sc))
if entry == nil {
log.Fatalf("%q does not match any active instance", args[0])
}
if err := syscall.Kill(entry.PID, syscall.SIGTERM); err != nil {
log.Fatalf("cannot terminate %s: %v", entry.ID.String(), err)
}
return errSuccess
})
{
var flagShort bool
c.NewCommand("ps", "List active instances", func(args []string) error {
+1
View File
@@ -25,6 +25,7 @@ commands:
run Load and start container from configuration file
exec Configure and start a permissive container
show Show live or local instance configuration
kill Terminate an active instance
ps List active instances
version Display version information
license Show full license text
+4
View File
@@ -1196,6 +1196,10 @@ func main() {
if w, ok := err.(interface{ Unwrap() []error }); !ok {
log.Fatal(err)
} else {
if _, ok = w.(pkg.InputError); ok {
log.Fatal(w)
}
errs := w.Unwrap()
for i, e := range errs {
if i == len(errs)-1 {
+2 -5
View File
@@ -118,11 +118,8 @@ func TestExec(t *testing.T) {
[]string{"testtool"},
pkg.MustPath("/proc/nonexistent", false, failingArtifact),
), nil, nil, pkg.WNew, &pkg.DependencyCureError{
{
A: failingArtifact,
Err: stub.UniqueError(0xcafe),
},
), nil, nil, pkg.WNew, pkg.InputError{
failingArtifact: stub.UniqueError(0xcafe),
}},
{"invalid paths", pkg.NewExec(
+48 -92
View File
@@ -15,10 +15,10 @@ import (
"hash"
"io"
"io/fs"
"iter"
"maps"
"math"
"os"
"os/signal"
"path/filepath"
"runtime"
"slices"
@@ -654,10 +654,10 @@ type pendingArtifactDep struct {
// if curing succeeds.
resP *cureRes
// Address of result error slice populated during [Cache.Cure], dereferenced
// Address of result error map populated during [Cache.Cure], dereferenced
// after acquiring errsMu if curing fails. No additional action is taken,
// [Cache] and its caller are responsible for further error handling.
errs *DependencyCureError
errs InputError
// Address of mutex synchronising access to errs.
errsMu *sync.Mutex
@@ -1721,109 +1721,61 @@ retry:
goto retry
}
// CureError wraps a non-nil error returned attempting to cure an [Artifact].
type CureError struct {
A Artifact
Err error
}
// An InputError describes inputs of a [FloodArtifact] which had failed to cure.
type InputError map[Artifact]error
// Unwrap returns the underlying error.
func (e *CureError) Unwrap() error { return e.Err }
// unwrap returns an iterator over sorted, deduplicated [Artifact] and their
// corresponding identifier.
func (e InputError) unwrap() iter.Seq2[Artifact, unique.Handle[ID]] {
ir := NewIR()
// Error returns the error message from the underlying Err.
func (e *CureError) Error() string { return e.Err.Error() }
// A DependencyCureError wraps errors returned while curing dependencies.
type DependencyCureError []*CureError
// unwrapM recursively expands underlying errors into a caller-supplied map.
func (e *DependencyCureError) unwrapM(
ctx context.Context,
ir *IRCache,
me map[unique.Handle[ID]]*CureError,
) {
for _, err := range *e {
if ctx.Err() != nil {
break
}
id := ir.Ident(err.A)
if _, ok := me[id]; ok {
continue
}
if _e, ok := err.Err.(*DependencyCureError); ok {
_e.unwrapM(ctx, ir, me)
continue
}
me[id] = err
type input struct {
a Artifact
id unique.Handle[ID]
}
}
// unwrap recursively expands and deduplicates underlying errors.
func (e *DependencyCureError) unwrap(
ctx context.Context,
ir *IRCache,
) DependencyCureError {
me := make(map[unique.Handle[ID]]*CureError)
e.unwrapM(ctx, ir, me)
type ent struct {
id unique.Handle[ID]
err *CureError
}
errs := make([]*ent, 0, len(me))
for id, err := range me {
errs = append(errs, &ent{id, err})
p := make([]input, 0, len(e))
for a := range e {
p = append(p, input{a, ir.Ident(a)})
}
var identBuf [2]ID
slices.SortFunc(errs, func(a, b *ent) int {
slices.SortFunc(p, func(a, b input) int {
identBuf[0], identBuf[1] = a.id.Value(), b.id.Value()
return slices.Compare(identBuf[0][:], identBuf[1][:])
})
p = slices.CompactFunc(p, func(a, b input) bool { return a.id == b.id })
_errs := make(DependencyCureError, len(errs))
for i, v := range errs {
_errs[i] = v.err
return func(yield func(Artifact, unique.Handle[ID]) bool) {
for _, i := range p {
if !yield(i.a, i.id) {
return
}
}
}
return _errs
}
// Unwrap returns a deduplicated slice of underlying errors.
func (e *DependencyCureError) Unwrap() []error {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
errs := e.unwrap(ctx, NewIR())
_errs := make([]error, len(errs))
for i, err := range errs {
_errs[i] = err
}
return _errs
}
// Error returns a user-facing multiline error message.
func (e *DependencyCureError) Error() string {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
ir := NewIR()
errs := e.unwrap(ctx, ir)
if len(errs) == 0 {
return "invalid dependency cure outcome"
}
// Error returns a user-facing, deterministic text representation of e.
func (e InputError) Error() string {
var buf strings.Builder
buf.WriteString("errors curing dependencies:")
for _, err := range errs {
buf.WriteString("\n\t" +
reportName(err.A, ir.Ident(err.A)) + ": " +
err.Error())
}
if ctx.Err() != nil {
buf.WriteString("\nerror resolution cancelled")
buf.WriteString("errors curing inputs:")
for a, id := range e.unwrap() {
buf.WriteString("\n\t")
buf.WriteString(reportName(a, id))
buf.WriteString(": ")
buf.WriteString(e[a].Error())
}
return buf.String()
}
// Unwrap returns a slice of underlying errors sorted by identifier.
func (e InputError) Unwrap() []error {
errs := make([]error, 0, len(e))
for a := range e.unwrap() {
errs = append(errs, e[a])
}
return errs
}
// enterCure must be called before entering an [Artifact] implementation.
func (c *Cache) enterCure(a Artifact, curesExempt bool) error {
if c.attr.Notify != nil {
@@ -2023,7 +1975,7 @@ func (c *Cache) cureMany(
wg.Add(len(inputs))
var mask []bool
res := make([]cureRes, len(inputs))
errs := make(DependencyCureError, 0, len(inputs))
errs := make(InputError)
var errsMu sync.Mutex
if shallow {
mask = make([]bool, len(inputs))
@@ -2042,13 +1994,13 @@ func (c *Cache) cureMany(
continue
}
}
pending := pendingArtifactDep{d, &res[i], &errs, &errsMu, &wg}
pending := pendingArtifactDep{d, &res[i], errs, &errsMu, &wg}
go pending.cure(c)
}
wg.Wait()
if len(errs) > 0 {
return mask, &errs
return mask, errs
}
for i, p := range res {
if shallow && mask[i] {
@@ -2651,7 +2603,11 @@ func (pending *pendingArtifactDep) cure(c *Cache) {
}
pending.errsMu.Lock()
*pending.errs = append(*pending.errs, &CureError{pending.a, err})
if errs, ok := err.(InputError); ok {
maps.Copy(pending.errs, errs)
} else {
pending.errs[pending.a] = err
}
pending.errsMu.Unlock()
}
+42 -59
View File
@@ -861,14 +861,11 @@ func TestCache(t *testing.T) {
cure: func(f *pkg.FContext) error {
panic("attempting to cure impossible artifact")
},
}, nil, nil, pkg.WNew, &pkg.DependencyCureError{
{
A: failingFile,
Err: struct {
_ []byte
stub.UniqueError
}{UniqueError: 0xbad},
},
}, nil, nil, pkg.WNew, pkg.InputError{
failingFile: struct {
_ []byte
stub.UniqueError
}{UniqueError: 0xbad},
}},
})
@@ -1949,7 +1946,7 @@ errors during scrub:
}
}
func TestDependencyCureError(t *testing.T) {
func TestInputError(t *testing.T) {
t.Parallel()
makeIdent := func(ident ...byte) pkg.Artifact {
@@ -1962,56 +1959,40 @@ func TestDependencyCureError(t *testing.T) {
testCases := []struct {
name string
err pkg.DependencyCureError
err pkg.InputError
want string
unwrap []error
}{
{"simple", pkg.DependencyCureError{
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
}, `errors curing dependencies:
{"simple", pkg.InputError{
makeIdent(0xff, 9): stub.UniqueError(0xbad09),
makeIdent(0xff, 0): stub.UniqueError(0xbad00),
makeIdent(0xff, 0xf): stub.UniqueError(0xbad0f),
makeIdent(0xff, 1): stub.UniqueError(0xbad01),
}, `errors curing inputs:
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{
&pkg.CureError{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
&pkg.CureError{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
&pkg.CureError{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
&pkg.CureError{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
stub.UniqueError(0xbad00),
stub.UniqueError(0xbad01),
stub.UniqueError(0xbad09),
stub.UniqueError(0xbad0f),
}},
{"dedup", pkg.DependencyCureError{
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
{A: makeIdent(0xff, 0xfd), Err: &pkg.DependencyCureError{
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
{A: makeIdent(0xff, 0xc), Err: &pkg.DependencyCureError{
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
}},
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
}},
{A: makeIdent(0xff, 0xff), Err: &pkg.DependencyCureError{
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
{A: makeIdent(0xff, 0xc), Err: &pkg.DependencyCureError{
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
}},
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
}},
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
}, `errors curing dependencies:
{"dedup", pkg.InputError{
makeIdent(0xff, 9): stub.UniqueError(0xbad09),
makeIdent(0xff, 9): stub.UniqueError(0xbad09),
makeIdent(0xff, 9): stub.UniqueError(0xbad09),
makeIdent(0xff, 0): stub.UniqueError(0xbad00),
makeIdent(0xff, 0): stub.UniqueError(0xbad00),
makeIdent(0xff, 1): stub.UniqueError(0xbad01),
}, `errors curing inputs:
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{
&pkg.CureError{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)},
&pkg.CureError{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)},
&pkg.CureError{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
&pkg.CureError{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite`, []error{
stub.UniqueError(0xbad00),
stub.UniqueError(0xbad01),
stub.UniqueError(0xbad09),
}},
}
for _, tc := range testCases {
@@ -2055,19 +2036,21 @@ func (a earlyFailureF) Cure(*pkg.FContext) error {
func BenchmarkEarlyDCE(b *testing.B) {
msg := message.New(log.New(os.Stderr, "dce: ", 0))
msg.SwapVerbose(testing.Verbose())
c, err := pkg.Open(b.Context(), msg, check.MustAbs(b.TempDir()), nil)
if err != nil {
b.Fatal(err)
}
_, _, err = c.Cure(earlyFailureF(8))
if !errors.Is(err, stub.UniqueError(0xcafe)) {
b.Fatalf("Cure: error = %v", err)
}
c.Close()
dce := err.(*pkg.DependencyCureError)
for b.Loop() {
dce.Unwrap()
b.StopTimer()
c, err := pkg.Open(b.Context(), msg, check.MustAbs(b.TempDir()), nil)
if err != nil {
b.Fatal(err)
}
b.StartTimer()
_, _, err = c.Cure(earlyFailureF(8))
b.StopTimer()
if !errors.Is(err, stub.UniqueError(0xcafe)) {
b.Fatalf("Cure: error = %v", err)
}
c.Close()
b.StartTimer()
}
}
+59 -6
View File
@@ -12,7 +12,7 @@ import (
// Value are types supported by the language.
type Value interface {
bool | int64 | string | []string | []int64 | [][2]string
bool | int64 | string | []string | []int64 | [][2]string | Nil
}
type (
@@ -33,6 +33,29 @@ type (
F func(args FArgs) (v any, set bool, err error)
V map[unique.Handle[Ident]]any
}
// Nil represents an untyped nil.
Nil struct{}
// AString represents an argument string that may be nil.
AString struct {
V string
Nil bool
}
)
// NilError is returned for an invalid nil assignment.
type NilError struct{ reflect.Type }
func (e NilError) Error() string {
return fmt.Sprintf("attempting to assign nil to %s", e.Type)
}
var (
// nilStringV is the [reflect.Value] of an Azalea nil assigned to an [AString].
nilStringV = reflect.ValueOf(AString{Nil: true})
// nilStringT is the [reflect.Type] of nilStringV.
nilStringT = nilStringV.Type()
)
// Apply applies named arguments and rejects unused arguments.
@@ -50,8 +73,8 @@ func (args FArgs) Apply(v map[unique.Handle[Ident]]any) error {
}
return UndefinedError(arg.K.Value())
}
err := storeE(r, arg.V)
if err != nil {
if err := storeE(r, arg.V); err != nil {
return err
}
}
@@ -115,11 +138,38 @@ func (e TypeError) Is(err error) bool {
}
// storeE is a convenience function to set the value of a result pointer.
func storeE(rp any, r any) error {
func storeE(rp, r any) error {
pv := reflect.ValueOf(rp).Elem()
pt := pv.Type()
as := nilStringT.AssignableTo(pt)
if r == (Nil{}) {
switch kind := pt.Kind(); kind {
case reflect.Bool, reflect.String:
return NilError{pt}
default:
if rv, ok := rp.(*any); ok && !reflect.ValueOf(*rv).IsValid() {
*rv = Nil{}
} else if as {
pv.Set(nilStringV)
} else {
pv.SetZero()
}
return nil
}
}
v := reflect.ValueOf(r)
pt, vt := pv.Type(), v.Type()
if !vt.AssignableTo(pt) {
if vt := v.Type(); !vt.AssignableTo(pt) {
if as {
var asv AString
if err := storeE(&asv.V, r); err != nil {
return err
}
pv.Set(reflect.ValueOf(asv))
return nil
}
return TypeError{vt, pt}
}
pv.Set(v)
@@ -226,6 +276,9 @@ func evaluateAny(d PF, s []Frame, expr, rp any) bool {
case "false":
store(rp, false)
return true
case "nil":
store(rp, Nil{})
return true
default:
return evaluateAny(d, s, v, rp)
}
+69 -5
View File
@@ -100,15 +100,79 @@ func TestEvaluate(t *testing.T) {
Err: UndefinedError("f"),
}},
{"error wrap deep", `f { v = nil; }`, makeStackCheck(func(
{"error wrap deep", `f { v = nonexistent; }`, makeStackCheck(func(
FArgs,
) (any, error) {
panic("unreachable")
}), "", EvaluationError{
Expr: Ident("nil"),
Err: UndefinedError("nil"),
Expr: Ident("nonexistent"),
Err: UndefinedError("nonexistent"),
}},
{"nil", `f { v = nil; }`, checkArgs(FArgs{
{K: unique.Make(Ident("v")), V: Nil{}},
}), "\xfd", nil},
{"apply nil string", `f { v = nil; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
var s string
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &s,
})
v = s
return
}), "", EvaluationError{
Expr: Func{
Ident: Ident("f"),
Args: []Arg{
{K: []Ident{"v"}, V: Val{Ident("nil")}},
},
},
Err: NilError{Type: reflect.TypeFor[string]()},
}},
{"apply nil AString", `f { v = nil; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
s := AString{}
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &s,
})
v = s.V
if !s.Nil {
err = fmt.Errorf("got non-nil string %q", s.V)
}
return
}), "", nil},
{"apply AString", `f { v = "\xfd"; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
s := AString{}
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &s,
})
v = s.V
if s.Nil {
err = fmt.Errorf("unexpected nil %q", s.V)
}
return
}), "\xfd", nil},
{"apply nil", `f { v = nil; }`, makeStackCheck(func(
args FArgs,
) (v any, err error) {
s := make([]struct{}, 9)
err = args.Apply(map[unique.Handle[Ident]]any{
unique.Make(Ident("v")): &s,
})
if s != nil {
err = fmt.Errorf("got non-nil value %#v", s)
}
return
}), "", nil},
{"common inputs", `package name { inputs, v = []; }`, nil, "", EvaluationError{
Expr: Func{
Ident: Ident("name"),
@@ -214,8 +278,8 @@ func TestEvaluate(t *testing.T) {
}
var errEquals bool
if _, ok := errors.AsType[TypeError](err); ok {
errEquals = errors.Is(err, tc.err)
if e, ok := errors.AsType[TypeError](err); ok {
errEquals = e.Is(tc.err)
} else {
errEquals = reflect.DeepEqual(err, tc.err)
}
+1 -1
View File
@@ -39,7 +39,7 @@ package acl {
exec = make {
// makes assumptions about uid_map/gid_map
skipCheck = true;
check = nil;
};
inputs = [ attr, kernel-headers ];
+3 -3
View File
@@ -15,9 +15,9 @@ package awk {
chmod = true;
exec = make {
omitDefaults = true;
inPlace = true;
skipConfigure = true;
defaults = false;
chdir = false;
configure = nil;
make = [ "YACC='yacc -d -b awkgram'" ];
preCheck = "install -vD a.out /system/bin/awk\n";
install = "install -vD a.out /work/system/bin/awk";
+1 -1
View File
@@ -12,7 +12,7 @@ package bison {
toyboxEarly = true;
exec = make {
omitDefaults = true;
defaults = false;
check = [
"TESTSUITEFLAGS=" + jobsFlagE + "' " + skipGNUTests {
tests = [
+1 -1
View File
@@ -19,6 +19,6 @@ package byacc {
chmod = true;
exec = make {
omitDefaults = true;
defaults = false;
};
}
+4 -7
View File
@@ -15,13 +15,10 @@ package bzip2 {
enterSource = true;
exec = make {
skipConfigure = true;
skipCheck = true;
inPlace = true;
make = [
"CC=cc",
];
chdir = false;
configure = nil;
make = [ "CC=cc" ];
check = nil;
install = "make PREFIX=/work/system install";
};
}
+1 -1
View File
@@ -27,7 +27,7 @@ package cairo {
// runs the entire test suite in a single meson test
interactiveTest = true;
// only works with specific dependency versions
skipTest = true;
test = false;
};
inputs = [
+1 -1
View File
@@ -20,7 +20,7 @@ package cmake {
chmod = true;
exec = make {
omitDefaults = true;
defaults = false;
configureName = "/usr/src/cmake/bootstrap";
configure = {
+1 -1
View File
@@ -19,7 +19,7 @@ package connman {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
dbus,
iptables,
+1 -1
View File
@@ -21,7 +21,7 @@ touch \
`;
exec = make {
inPlace = true;
chdir = false;
configureName = "../dist/configure";
forceAutoconf = true;
configure = {
+2 -2
View File
@@ -41,11 +41,11 @@ package xdg-dbus-proxy {
website = "https://github.com/flatpak/xdg-dbus-proxy";
anitya = 58434;
version# = "0.1.7";
version# = "0.1.8";
source = remoteGitHub {
suffix = "flatpak/xdg-dbus-proxy";
tag = version;
checksum = "UW5Pe-TP-XAaN-kTbxrkOQ7eYdmlAQlr2pdreLtPT0uwdAz-7rzDP8V_8PWuZBup";
checksum = "ygdW0EEvZ-_PJfnFTNoobITmRzqJecTinBsJd_iJQrRvzidwqESCjeNkB55smZ2y";
};
exec = meson {
+4 -4
View File
@@ -18,17 +18,17 @@ package elfutils {
];
exec = make {
// nonstandard glibc extension
skipCheck = true;
configure = {
"enable-deterministic-archives";
};
// nonstandard glibc extension
check = nil;
};
inputs = [
m4,
pkg-config,
pkgconf,
zlib,
bzip2,
+6 -6
View File
@@ -3,12 +3,12 @@ package firmware {
website = "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git";
anitya = 141464;
version# = "20260622";
version# = "20260810";
source = remoteGitLab {
domain = "gitlab.com";
suffix = "kernel-firmware/linux-firmware";
ref = version;
checksum = "gpytkDM58EVjaUuryOekcekh_rWsfuv3S7LQxopHlNlVGmMsuqNwfug4BjgTgizE";
checksum = "XNUhz9QstaDKNegM3Bl0-TtZzpsvX7-E8WMnDCO7KBhBC6t_TxsdG05-ETdXynry";
};
// dedup creates temporary file
@@ -22,17 +22,17 @@ package firmware {
];
exec = make {
omitDefaults = true;
skipConfigure = true;
inPlace = true;
defaults = false;
chdir = false;
configure = nil;
make = [
"DESTDIR=/work/system",
"install-zst",
];
// requires pre-commit
skipCheck = true;
check = nil;
install = "make " + jobsFlagE + " " + loadFlagE + " DESTDIR=/work/system dedup";
};
+1 -1
View File
@@ -18,7 +18,7 @@ package fontconfig {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
gettext,
gperf,
gzip,
+1 -1
View File
@@ -22,7 +22,7 @@ package fuse {
postCompile = "python3 -m pytest test/";
// this project uses pytest
skipTest = true;
test = false;
};
inputs = [
+1 -1
View File
@@ -65,7 +65,7 @@ ln -s system/lib /work/
// This toolchain is hacked to pieces, it is not expected to ever work
// well in its current state. That does not matter as long as the
// toolchain it produces passes its own test suite.
skipCheck = true;
check = nil;
};
inputs = [
+1 -1
View File
@@ -23,7 +23,7 @@ rm -f /system/bin/httpd
bin = [ "perl" ];
populateUsrBin = true;
exec = make {
inPlace = true;
chdir = false;
generate = "make configure";
preMake = `
+9 -9
View File
@@ -19,7 +19,7 @@ chmod +w tests/test-c32ispunct.sh && echo '#!/bin/sh' > tests/test-c32ispunct.sh
toyboxEarly = true;
exec = make {
omitDefaults = true;
defaults = false;
};
inputs = [
@@ -114,7 +114,7 @@ package libtool {
exec = make {
// _Z2a2c: symbol not found
skipEarlyStageCheck = true;
checkEarly = false;
check = [
"TESTSUITEFLAGS=" + jobsFlagE,
@@ -142,7 +142,7 @@ package gzip {
exec = make {
// dependency loop
skipCheck = true;
check = nil;
};
}
@@ -197,7 +197,7 @@ test_disable '#!/bin/sh' tests/cmp
toyboxEarly = true;
exec = make {
omitDefaults = true;
defaults = false;
};
}
@@ -223,7 +223,7 @@ test_disable '#!/bin/sh' tests/need-filename
toyboxEarly = true;
exec = make {
omitDefaults = true;
defaults = false;
};
}
@@ -334,7 +334,7 @@ package bash {
toyboxEarly = true;
exec = make {
omitDefaults = true;
defaults = false;
configure = {
"without-bash-malloc";
};
@@ -371,7 +371,7 @@ test_disable 'int main(){return 0;}' gnulib-tests/test-lchown.c
`;
exec = make {
omitDefaults = true;
defaults = false;
configure = {
"enable-single-binary": "symlinks";
};
@@ -436,7 +436,7 @@ package texinfo {
exec = make {
// nonstandard glibc extension
skipCheck = true;
check = nil;
};
inputs = [ perl ];
@@ -648,7 +648,7 @@ package mpc {
enterSource = true;
exec = make {
inPlace = true;
chdir = false;
generate = "autoreconf -vfi";
};
+1 -1
View File
@@ -47,7 +47,7 @@ echo 'int main(){return 0;}' > tests/mini-dtls-fragments.c
bison,
gettext,
gperf,
pkg-config,
pkgconf,
python,
texinfo,
-135
View File
@@ -1,135 +0,0 @@
From 06f90ebfa6f3e0a744584513e2786988b26569da Mon Sep 17 00:00:00 2001
From: Damien Neil <dneil@google.com>
Date: Wed, 08 Jul 2026 11:11:48 -0700
Subject: [PATCH] os: properly handle trailing / in Root.MkdirAll
MkdirAll("dir/") should create "dir", not return an error.
Fixes #80308
Change-Id: I75458c30b6cb94be3a3d368f6024caef6a6a6964
---
diff --git a/src/os/root_noopenat.go b/src/os/root_noopenat.go
index 228b580..a84e952 100644
--- a/src/os/root_noopenat.go
+++ b/src/os/root_noopenat.go
@@ -158,6 +158,9 @@
if err := checkPathEscapes(r, name); err == errPathEscapes {
return &PathError{Op: "mkdirat", Path: name, Err: err}
}
+ if name == "" {
+ return &PathError{Op: "mkdirat", Path: name, Err: syscall.ENOENT}
+ }
prefix := r.root.name + string(PathSeparator)
if err := MkdirAll(prefix+name, perm); err != nil {
if pe, ok := err.(*PathError); ok {
diff --git a/src/os/root_openat.go b/src/os/root_openat.go
index d7c9334..92865e4 100644
--- a/src/os/root_openat.go
+++ b/src/os/root_openat.go
@@ -167,6 +167,12 @@
fi, e := r.Stat(fullname)
if e == nil && fi.Mode().IsDir() {
err = nil
+ } else if e == nil {
+ err = syscall.ENOTDIR
+ } else if !IsNotExist(e) {
+ // EPERM, ELOOP, etc.,
+ // probably more useful than EEXIST.
+ err = e
}
}
}
@@ -177,7 +183,12 @@
}
return struct{}{}, &PathError{Op: "mkdirat", Err: err}
}
- _, err := doInRoot(r, fullname, 0, openDirFunc, openLastComponentFunc)
+ flags := uint(doInRootCreatingDirectory)
+ switch runtime.GOOS {
+ case "linux", "windows":
+ flags = doInRootNoHandleTerminalSlash // see rootMkdir
+ }
+ _, err := doInRoot(r, fullname, flags, openDirFunc, openLastComponentFunc)
if err != nil {
if _, ok := err.(*PathError); !ok {
err = &PathError{Op: "mkdirat", Path: fullname, Err: err}
diff --git a/src/os/root_test.go b/src/os/root_test.go
index 5e0acf9..33a2f33 100644
--- a/src/os/root_test.go
+++ b/src/os/root_test.go
@@ -585,6 +585,11 @@
func TestRootMkdirAll(t *testing.T) {
for _, test := range rootTestCases {
+ if test.name == "directory does not exist" {
+ // Test expects error, mkdirall creates the missing directory.
+ // TestRootMultiMkdirAll covers this case better anyway, just skip.
+ continue
+ }
test.run(t, func(t *testing.T, target string, root *os.Root) {
wantError := test.wantError
if test.ltarget != "" {
@@ -593,7 +598,7 @@
wantError = true
}
- err := root.Mkdir(test.open, 0o777)
+ err := root.MkdirAll(test.open, 0o777)
if errEndsTest(t, err, wantError, "root.MkdirAll(%q)", test.open) {
return
}
@@ -3133,6 +3138,52 @@
})
}
+func TestRootMultiMkdirAllShallow(t *testing.T) {
+ runRootMultiTest(t, func(t *testing.T, test *rootMultiTest) (string, error) {
+ return testRootMultiMkdirAll(t, test, test.targetPath)
+ })
+}
+
+func TestRootMultiMkdirAllDeep(t *testing.T) {
+ runRootMultiTest(t, func(t *testing.T, test *rootMultiTest) (string, error) {
+ targetPath := test.targetPath
+ if len(targetPath) > 0 && os.IsPathSeparator(targetPath[len(targetPath)-1]) {
+ targetPath += "a/b/"
+ } else {
+ targetPath += "/a/b"
+ }
+ return testRootMultiMkdirAll(t, test, targetPath)
+ })
+}
+
+func testRootMultiMkdirAll(t *testing.T, test *rootMultiTest, targetPath string) (string, error) {
+ var mkdirAll = os.MkdirAll
+ if test.root != nil {
+ mkdirAll = test.root.MkdirAll
+ }
+
+ test.setOp("MkdirAll(%q, 0o777)", targetPath)
+ gotErr := mkdirAll(targetPath, 0o777)
+
+ switch {
+ case test.root != nil && test.target.lescapes():
+ // "mkdir ../target", or equivalent escaping path.
+ test.wantError(t, gotErr, os.ErrPathEscapes)
+ case test.root != nil && test.target.escapes():
+ // "mkdir ../target", or equivalent escaping path.
+ test.wantError(t, gotErr, errAny)
+ return "", errSkipRootConsistencyCheck
+ case test.root != nil && test.target.kind == testFileSymlink && test.target.target.kind == testFileAbsent && targetPath != test.targetPath:
+ // A minor inconsistency between Root.MkdirAll and os.MkdirAll:
+ // When an intermediate component of the tree being constructed is a
+ // dangling symlink, Root.MkdirAll will follow the symlink and create
+ // its target directory, while os.MkdirAll will fail with an error.
+ return "", errSkipRootConsistencyCheck
+ default:
+ }
+ return "", gotErr
+}
+
func TestRootMultiRename(t *testing.T) {
if runtime.GOOS == "wasip1" {
switch os.Getenv("GOWASIRUNTIME") {
+3 -5
View File
@@ -3,18 +3,16 @@ package go {
website = "https://go.dev";
anitya = 1227;
version# = "1.26.5";
version# = "1.26.6";
source = remoteTar {
url = "https://go.dev/dl/go"+version+".src.tar.gz";
checksum = "13yt1u_NGOd62LO-WZ8W6CUXodOrEF5CdkiTTiH9E635IHn1luvlXYjsHpBXNFSw";
checksum = "BJQz9rGJ7ElMsZGURH7lw48Hw0x88RwdQJpINMomtgGCMK3AtwGCxDRkLE9REh5r";
compress = gzip;
};
patches = [
// https://go.dev/issue/77674
"746640.patch",
// https://go.dev/issue/80308
"799064.patch",
];
env = [
@@ -27,7 +25,7 @@ package go {
enterSource = true;
exec = generic {
inPlace = true;
chdir = false;
build = `
mkdir /work/system/ "${TMPDIR}"
cp -r . /work/system/go
+2 -2
View File
@@ -3,12 +3,12 @@ package googletest {
exclude = true;
anitya = 18290;
version# = "1.17.0";
version# = "1.18.0";
output = remoteGitHubRelease {
suffix = "google/googletest";
tag = "v"+version;
name = "googletest-"+version+".tar.gz";
checksum = "-1r3ch8vPP8COF7xUH5hyX6bEJ4dN9TQh4IxrmpHr6vaig6mA3DdUpV4cihQ_9dw";
checksum = "ABVPC5sduQR7xfkZQm7UHSmBTaAJcVPRHS_lNMhlL99HU_YffpFmXbwRKeG1ZY8A";
compress = gzip;
};
}
@@ -2,11 +2,11 @@ package hakurei-source {
description = "hakurei source tree";
exclude = true;
version# = "0.4.5";
version# = "0.4.6";
output = remoteTar {
url = "https://git.gensokyo.uk/rosa/hakurei/archive/"+
"v"+version+".tar.gz";
checksum = "5bvbuIRcDIrtijogwqXn3y8h5f3rVS4ZSVhOig6Galfzt3g-O3Ufb-tHL1kQCQWK";
checksum = "2HxvdykuSSymAu-c1WIwQAy3qT4dDm8B--93iL4uomBlBC8wfSWldbvPF1noNkUC";
compress = gzip;
};
}
@@ -27,16 +27,9 @@ package hakurei {
"CC=clang -O3 -Werror",
];
files = {
"hostname/main.go": "hostname";
};
exec = generic {
inPlace = true;
chdir = false;
build = `
echo 'Building test helper (hostname).'
go build -o /bin/hostname /usr/src/hostname/main.go
mkdir -p /work/system/libexec/hakurei/
echo "Building hakurei for $(go env GOOS)/$(go env GOARCH)."
@@ -71,7 +64,8 @@ mkdir -p /work/system/bin/
inputs = [
go,
pkg-config,
pkgconf,
net-tools,
libseccomp,
acl,
@@ -98,16 +92,9 @@ package hakurei-dist {
"CC=clang -O3 -Werror",
];
files = {
"hostname/main.go": "hostname";
};
exec = generic {
inPlace = true;
chdir = false;
build = `
echo 'Building test helper (hostname).'
go build -o /bin/hostname /usr/src/hostname/main.go
NAME=make`;
check = `
NAME=all`;
@@ -118,7 +105,8 @@ DESTDIR=/work "./${NAME}.sh"
inputs = [
go,
pkg-config,
pkgconf,
net-tools,
libseccomp,
acl,
@@ -146,7 +134,7 @@ package earlyinit {
];
exec = generic {
inPlace = true;
chdir = false;
build = `
echo '# Building earlyinit.'
go build -trimpath -v -o /work/ -ldflags="-s -w
-11
View File
@@ -1,11 +0,0 @@
package main
import "os"
func main() {
if name, err := os.Hostname(); err != nil {
panic(err)
} else {
os.Stdout.WriteString(name)
}
}
+2 -2
View File
@@ -3,11 +3,11 @@ package harfbuzz {
website = "https://harfbuzz.github.io";
anitya = 1299;
version# = "14.3.0";
version# = "14.3.1";
source = remoteGitHub {
suffix = "harfbuzz/harfbuzz";
tag = version;
checksum = "C03eSJbyFvrOPXWhlHgwxfqUKyR9xQO_FKzbwQzT7hW9DTUAQIiwvUIf_6cqaKPm";
checksum = "ykVwQNNbvY38Y27VjAfk16SGcEO5NY5A8CFxJCJ8z0ARh5MdLImmONpy-ZSb79Il";
};
exec = meson {
+2 -2
View File
@@ -15,9 +15,9 @@ package hwdata {
exec = make {
// awk: fatal: cannot open file `hwdata.spec' for reading: No such file or directory
inPlace = true;
chdir = false;
// lspci: Unknown option 'A' (see "lspci --help")
skipCheck = true;
check = nil;
};
}
+3 -3
View File
@@ -21,7 +21,7 @@ package iproute2 {
chmod = true;
exec = make {
inPlace = true;
chdir = false;
// drop default autoconf options
configureName = "./configure";
configure = {
@@ -30,11 +30,11 @@ package iproute2 {
};
make = [ "CC=cc", "YACC=yacc" ];
// wants root
skipCheck = true;
check = nil;
};
inputs = [
pkg-config,
pkgconf,
m4,
byacc,
flex,
+1 -1
View File
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/x86 6.18.43 Kernel Configuration
# Linux/x86 6.18.44 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="clang version 22.1.8"
CONFIG_GCC_VERSION=0
+1 -1
View File
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/arm64 6.18.43 Kernel Configuration
# Linux/arm64 6.18.44 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="clang version 22.1.8"
CONFIG_GCC_VERSION=0
+13 -12
View File
@@ -3,11 +3,11 @@ package kernel-source {
website = "https://kernel.org";
exclude = true;
version# = "6.18.43";
version# = "6.18.44";
output = remoteTar {
url = "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+
"snapshot/linux-"+version+".tar.gz";
checksum = "SthN8PgD7oze4syBC54KJoky7JUpAmXJO0Y98an1ZJiqGppnf6N3kmZiZZdvi9dd";
checksum = "yNPGMl3A-EgU6LgD37PAcXIa9iUtP-AmoJuQozfGRSq6Eg1Eq4fdbpKy3iWewU9_";
compress = gzip;
};
}
@@ -25,8 +25,8 @@ package kernel-headers {
toyboxEarly = true;
exec = make {
omitDefaults = true;
skipConfigure = true;
defaults = false;
configure = nil;
make = [
"-f /usr/src/kernel-headers/Makefile",
"O=/tmp/kbuild",
@@ -35,7 +35,7 @@ package kernel-headers {
"INSTALL_HDR_PATH=/work/system",
"headers_install",
];
skipCheck = true;
check = nil;
install = `
cat \
/usr/src/version.h > \
@@ -46,9 +46,9 @@ cat \
checksum = arch {
default = "";
amd64 = "mZZqI0tEpqbr3sQKOFLBeNv-DC7pkHNqPI7JdSSmo40sFCF2XnAMcah1DcUK2HTe";
arm64 = "e6cD6TsBr1e-zONKtocvbRwmSnxqC_2K7A2KvMcO6lnpt4MXL1gsyx6k-BXqC19Z";
riscv64 = "cljgtOrTCpyXoQLaKVmnnWPbCWkoXuMIVNjc6YXsy-zgsFzRA-H8yfJ1NojS867z";
amd64 = "vN5Ts9yAlHTntcQcNGJSisY5guYsYfvGnQqI1NzTBzvhBMPD432WB3B0KFGYQntA";
arm64 = "FQtpqCA0tlz17RJP8a5t9YEM_6F9kGPqQ9Z60gFrkVP3v8_P-Vnf5S7wLlxyRlOe";
riscv64 = "U5yQ9TI5_7diyrCcm2Iqh3XCMl0P60oQGeDMWxt3OQ91zFWPQ5FCH-eoYG9tSTMT";
};
inputs = [ rsync ];
}
@@ -86,11 +86,12 @@ install -Dm0500 \
exclusive = true;
exec = make {
omitDefaults = true;
skipConfigure = true;
defaults = false;
configure = nil;
// Build, install, and boot kernel before running kselftest on it.
skipCheck = true;
check = nil;
make = [
"-f /usr/src/kernel/Makefile",
@@ -154,7 +155,7 @@ package gen_init_cpio {
enterSource = true;
exec = generic {
inPlace = true;
chdir = false;
build = `
mkdir -p /work/system/bin/
cc -o /work/system/bin/gen_init_cpio usr/gen_init_cpio.c
+1 -1
View File
@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/riscv 6.18.43 Kernel Configuration
# Linux/riscv 6.18.44 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="clang version 22.1.8"
CONFIG_GCC_VERSION=0
+2 -2
View File
@@ -1,5 +1,5 @@
#define LINUX_VERSION_CODE 397866
#define LINUX_VERSION_CODE 397868
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
#define LINUX_VERSION_MAJOR 6
#define LINUX_VERSION_PATCHLEVEL 18
#define LINUX_VERSION_SUBLEVEL 42
#define LINUX_VERSION_SUBLEVEL 44
+1 -1
View File
@@ -22,7 +22,7 @@ package kmod {
};
// makes assumptions about the running kernel
skipTest = true;
test = false;
};
inputs = [
+2 -2
View File
@@ -18,8 +18,8 @@ package libaio {
env = [ "PATH=/system/sbin" ];
bin = [ "bash" ];
exec = make {
inPlace = true;
skipConfigure = true;
chdir = false;
configure = nil;
preCheck = "rm harness/cases/20.t; "+ // flaky
"CFLAGS='"+
"-Wno-unknown-warning-option "+
+3 -3
View File
@@ -16,9 +16,9 @@ package libbpf {
chmod = true;
exec = make {
inPlace = true;
skipConfigure = true;
skipCheck = true;
chdir = false;
configure = nil;
check = nil;
install = "make DESTDIR=/work LIBSUBDIR=lib install";
};
+4 -12
View File
@@ -23,18 +23,10 @@ package libcap {
bin = [ "bash" ];
exec = make {
skipConfigure = true;
inPlace = true;
make = [
"CC=cc",
"all",
];
check = [
"CC=cc",
"test",
];
chdir = false;
configure = nil;
make = [ "CC=cc", "all" ];
check = [ "CC=cc", "test" ];
};
inputs = [
+2 -2
View File
@@ -3,7 +3,7 @@ package libexpat {
website = "https://libexpat.github.io";
anitya = 770;
version# = "2.8.2";
version# = "2.8.3";
source = remoteGitHubRelease {
suffix = "libexpat/libexpat";
tag = "R_"+replace {
@@ -12,7 +12,7 @@ package libexpat {
new = "_";
};
name = "expat-"+version+".tar.bz2";
checksum = "98Pdyj5QtO7QRtNFXTWsCNCixQDx701ZGql2B-JIrTDkw49J5WXXUwnS4AdMlM4L";
checksum = "prHQc14YY3Gp6BfflneNcVyRXM-AxFCqiigxrGL9TT1sGhVODvI_9JNR2xnZlZSj";
compress = bzip2;
};
+3 -3
View File
@@ -3,12 +3,12 @@ package libpsl {
website = "https://rockdaboot.github.io/libpsl";
anitya = 7305;
version# = "0.23.1";
version# = "0.23.2";
source = remoteGitHubRelease {
suffix = "rockdaboot/libpsl";
tag = version;
name = "libpsl-"+version+".tar.gz";
checksum = "9wu0JxiNGfY3TuYeCmOq9Xm3faPHole5is_3ZL2KUCh8FyaYwpl7a85SNsz8FmPz";
checksum = "-XIKaQK0QoyzXpwezyvGzDdIBCUTqPyd8jU6axIusrnma-qsYxhLUO1Oycwcelr2";
compress = gzip;
};
@@ -22,7 +22,7 @@ test_disable 'int main(){return 0;}' tests/test-is-public-builtin.c
exec = make {};
inputs = [
pkg-config,
pkgconf,
python,
];
}
+2 -2
View File
@@ -20,7 +20,7 @@ package libtirpc {
exec = make {
generate = "sh -e ./bootstrap";
configure = {
"CFLAGS": `"$(pkg-config --cflags libbsd-overlay) ${CFLAGS:-}"`;
"CFLAGS": `"$(pkgconf --cflags libbsd-overlay) ${CFLAGS:-}"`;
"disable-gssapi";
};
};
@@ -28,7 +28,7 @@ package libtirpc {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
libbsd,
kernel-headers,
+4 -6
View File
@@ -16,13 +16,11 @@ package libucontext {
enterSource = true;
exec = make {
omitDefaults = true;
skipConfigure = true;
inPlace = true;
defaults = false;
chdir = false;
make = [
"ARCH=" + linuxArch,
];
configure = nil;
make = [ "ARCH=" + linuxArch ];
install = "make prefix=/system DESTDIR=/work install";
};
}
+2 -2
View File
@@ -15,14 +15,14 @@ package libxslt {
generate = "NOCONFIGURE=1 ./autogen.sh";
// python libxml2 cyclic dependency
skipCheck = true;
check = nil;
};
inputs = [
automake,
libtool,
python,
pkg-config,
pkgconf,
libxml2,
];
+1 -1
View File
@@ -7,7 +7,7 @@ package lit {
exec = pip {
append = [ "llvm", "utils", "lit" ];
// already checked during llvm
skipCheck = true;
check = nil;
};
inputs = [ python-setuptools ];
+2 -2
View File
@@ -56,7 +56,7 @@ message(NOTICE "${LLVM_VERSION_MAJOR}")
"COMPILER_RT_BUILD_PROFILE": "OFF";
"COMPILER_RT_BUILD_XRAY": "OFF";
};
skipTest = true;
test = nil;
postInstall = `
mkdir -p "/work/system/lib/clang/$LLVM_VERSION_MAJOR/lib/"
ln -s \
@@ -119,7 +119,7 @@ package early-runtimes {
"LLVM_ENABLE_ZSTD": "FORCE_ON";
"LLVM_ENABLE_LIBXML2": "OFF";
};
skipTest = true;
test = nil;
};
inputs = [
+4 -14
View File
@@ -17,20 +17,10 @@ package lm_sensors {
bin = [ "perl" ];
populateUsrBin = true;
exec = make {
inPlace = true;
skipConfigure = true;
make = [
"CC=cc",
"ETCDIR=/system/etc",
"PREFIX=/system",
];
check = [
"CC=cc",
"check",
];
chdir = false;
configure = nil;
make = [ "CC=cc", "ETCDIR=/system/etc", "PREFIX=/system" ];
check = [ "CC=cc", "check" ];
install = "make DESTDIR=/work PREFIX=/system install";
};
+2 -2
View File
@@ -20,8 +20,8 @@ package lua {
chmod = true;
exec = make {
inPlace = true;
skipConfigure = true;
chdir = false;
configure = nil;
make = [ "CC='clang -fPIC'", "all" ];
check = [ "test" ];
install = `
+2 -2
View File
@@ -16,11 +16,11 @@ package lvm2 {
exec = make {
// requires root
skipCheck = true;
check = nil;
};
inputs = [
pkg-config,
pkgconf,
libaio,
kernel-headers,
+2 -2
View File
@@ -3,11 +3,11 @@ package meson {
website = "https://mesonbuild.com";
anitya = 6472;
version# = "1.11.2";
version# = "1.12.0";
source = remoteGitHub {
suffix = "mesonbuild/meson";
tag = version;
checksum = "9AMilGxTOVqPA2DaGMASyuVs1BeTzgDZ0NH2oSYoRZk846ApvfOBa4cc18XEEK7M";
checksum = "K0hm0h26_6e3-1poYZKwj18IB6bdAtYE-whpROtTCSpVN5GllwSwbXC2xPYcSFAJ";
};
patches = [
"respect-colour.patch",
+1 -1
View File
@@ -21,6 +21,6 @@ package musl-fts {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
];
}
+1 -1
View File
@@ -21,6 +21,6 @@ package musl-obstack {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
];
}
+5 -11
View File
@@ -23,14 +23,9 @@ package musl-headers {
];
exec = make {
omitDefaults = true;
skipCheck = true;
make = [
"DESTDIR=/work",
"install-headers",
];
defaults = false;
make = [ "DESTDIR=/work", "install-headers" ];
check = nil;
install = "# headers installed during make";
};
@@ -53,9 +48,8 @@ package musl {
];
exec = make {
omitDefaults = true;
skipCheck = true;
defaults = false;
check = nil;
postInstall = `
mkdir -p /work/system/bin
COMPAT_LINKER_NAME="ld-musl-` + linuxArch + `.so.1"
+1 -1
View File
@@ -19,7 +19,7 @@ package ncurses {
};
// "tests" are actual demo programs, not a test suite.
skipCheck = true;
check = nil;
postInstall = `
find /work/system/lib \
@@ -0,0 +1,115 @@
From 7a8f42fb20013a1493d8cae1c43436f85e656f2d Mon Sep 17 00:00:00 2001
From: Zephkeks <zephyrofficialdiscord@gmail.com>
Date: Tue, 13 May 2025 11:04:17 +0200
Subject: [PATCH] CVE-2025-46836: interface.c: Stack-based Buffer Overflow in
get_name()
Coordinated as GHSA-pfwf-h6m3-63wf
---
lib/interface.c | 63 ++++++++++++++++++++++++++++++-------------------
1 file changed, 39 insertions(+), 24 deletions(-)
diff --git a/lib/interface.c b/lib/interface.c
index 71d4163..a054f12 100644
--- a/lib/interface.c
+++ b/lib/interface.c
@@ -211,32 +211,47 @@ static int if_readconf(void)
}
static const char *get_name(char *name, const char *p)
+/* Safe version — guarantees at most IFNAMSIZ1 bytes are copied
+ and the destination buffer is always NULterminated. */
{
- while (isspace(*p))
- p++;
- while (*p) {
- if (isspace(*p))
- break;
- if (*p == ':') { /* could be an alias */
- const char *dot = p++;
- while (*p && isdigit(*p)) p++;
- if (*p == ':') {
- /* Yes it is, backup and copy it. */
- p = dot;
- *name++ = *p++;
- while (*p && isdigit(*p)) {
- *name++ = *p++;
- }
- } else {
- /* No, it isn't */
- p = dot;
- }
- p++;
- break;
- }
- *name++ = *p++;
+ char *dst = name; /* current write ptr */
+ const char *end = name + IFNAMSIZ - 1; /* last byte we may write */
+
+ /* Skip leading whitespace. */
+ while (isspace((unsigned char)*p))
+ ++p;
+
+ /* Copy until whitespace, end of string, or buffer full. */
+ while (*p && !isspace((unsigned char)*p) && dst < end) {
+ if (*p == ':') { /* possible alias veth0:123: */
+ const char *dot = p; /* remember the colon */
+ ++p;
+ while (*p && isdigit((unsigned char)*p))
+ ++p;
+
+ if (*p == ':') { /* confirmed alias */
+ p = dot; /* rewind and copy it all */
+
+ /* copy the colon */
+ if (dst < end)
+ *dst++ = *p++;
+
+ /* copy the digits */
+ while (*p && isdigit((unsigned char)*p) && dst < end)
+ *dst++ = *p++;
+
+ if (*p == ':') /* consume trailing colon */
+ ++p;
+ } else { /* if so treat as normal */
+ p = dot;
+ }
+ break; /* interface name ends here */
+ }
+
+ *dst++ = *p++; /* ordinary character copy */
}
- *name++ = '\0';
+
+ *dst = '\0'; /* always NULterminate */
return p;
}
From ddb0e375fb9ca95bb69335540b85bbdaa2714348 Mon Sep 17 00:00:00 2001
From: Bernd Eckenfels <net-tools@lina.inka.de>
Date: Sat, 17 May 2025 21:53:23 +0200
Subject: [PATCH] Interface statistic regression after 7a8f42fb2
---
lib/interface.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/interface.c b/lib/interface.c
index a054f12..ca4adf1 100644
--- a/lib/interface.c
+++ b/lib/interface.c
@@ -239,12 +239,11 @@ static const char *get_name(char *name, const char *p)
/* copy the digits */
while (*p && isdigit((unsigned char)*p) && dst < end)
*dst++ = *p++;
-
- if (*p == ':') /* consume trailing colon */
- ++p;
} else { /* if so treat as normal */
p = dot;
}
+ if (*p == ':') /* consume trailing colon */
+ ++p;
break; /* interface name ends here */
}
@@ -0,0 +1,53 @@
From a7926399a04ee8e629a02a2aeb6de1952d42d559 Mon Sep 17 00:00:00 2001
From: Bernd Eckenfels <net-tools@lina.inka.de>
Date: Sat, 17 May 2025 21:11:07 +0200
Subject: [PATCH] ipmaddr.c: Stack-based buffer Overflow in parse_hex()
Coordinated as GHSA-h667-qrp8-gj58.
---
ipmaddr.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/ipmaddr.c b/ipmaddr.c
index 64b7564..623fadd 100644
--- a/ipmaddr.c
+++ b/ipmaddr.c
@@ -91,17 +91,17 @@ static int parse_lla(char *str, char *addr)
return len;
}
-static int parse_hex(char *str, unsigned char *addr)
+static int parse_hex(char *str, unsigned char *dst, size_t dstlen)
{
int len=0;
- while (*str) {
+ while (len < dstlen && *str) {
int tmp;
if (str[1] == 0)
return -1;
if (sscanf(str, "%02x", &tmp) != 1)
return -1;
- addr[len] = tmp;
+ dst[len] = tmp;
len++;
str += 2;
}
@@ -152,7 +152,7 @@ void read_dev_mcast(struct ma_info **result_p)
m.addr.family = AF_PACKET;
- len = parse_hex(hexa, (unsigned char*)&m.addr.data);
+ len = parse_hex(hexa, (unsigned char*)&m.addr.data, sizeof(m.addr.data));
if (len >= 0) {
struct ma_info *ma = xmalloc(sizeof(m));
memcpy(ma, &m, sizeof(m));
@@ -222,7 +222,7 @@ void read_igmp6(struct ma_info **result_p)
m.addr.family = AF_INET6;
- len = parse_hex(hexa, (unsigned char*)&m.addr.data);
+ len = parse_hex(hexa, (unsigned char*)&m.addr.data, sizeof(m.addr.data));
if (len >= 0) {
struct ma_info *ma = xmalloc(sizeof(m));
memcpy(ma, &m, sizeof(m));
@@ -0,0 +1,71 @@
From 84041080a5d4794045b098ced90e0309bcbcff44 Mon Sep 17 00:00:00 2001
From: Zephkeks <zephyrofficialdiscord@gmail.com>
Date: Sat, 17 May 2025 22:11:37 +0200
Subject: [PATCH] proc.c: Stack-based Buffer Overflow in net-tools
(proc_gen_fmt)
Coordinated as GHSA-w7jq-cmw2-cq59.
---
lib/proc.c | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/lib/proc.c b/lib/proc.c
index d51d09f..02aae49 100644
--- a/lib/proc.c
+++ b/lib/proc.c
@@ -17,6 +17,8 @@ char *proc_gen_fmt(const char *name, int more, FILE * fh,...)
char buf[512], format[512] = "";
char *title, *head, *hdr;
va_list ap;
+ size_t format_len = 0;
+ size_t format_size = sizeof(format);
if (!fgets(buf, (sizeof buf) - 1, fh))
return NULL;
@@ -33,14 +35,43 @@ char *proc_gen_fmt(const char *name, int more, FILE * fh,...)
*hdr++ = 0;
if (!strcmp(title, head)) {
- strcat(format, va_arg(ap, char *));
+ const char *arg = va_arg(ap, char *);
+ size_t arg_len = strlen(arg);
+
+ /* Check if we have enough space for format specifier + space */
+ if (format_len + arg_len + 1 >= format_size) {
+ fprintf(stderr, "warning: format buffer overflow in %s\n", name);
+ va_end(ap);
+ return NULL;
+ }
+
+ strcpy(format + format_len, arg);
+ format_len += arg_len;
+
title = va_arg(ap, char *);
if (!title)
break;
} else {
- strcat(format, "%*s"); /* XXX */
+ /* Check if we have enough space for "%*s" */
+ if (format_len + 3 >= format_size) {
+ fprintf(stderr, "warning: format buffer overflow in %s\n", name);
+ va_end(ap);
+ return NULL;
+ }
+
+ strcpy(format + format_len, "%*s");
+ format_len += 3;
}
- strcat(format, " ");
+
+ /* Check if we have space for the trailing space */
+ if (format_len + 1 >= format_size) {
+ fprintf(stderr, "warning: format buffer overflow in %s\n", name);
+ va_end(ap);
+ return NULL;
+ }
+
+ format[format_len++] = ' ';
+ format[format_len] = '\0';
}
va_end(ap);
@@ -0,0 +1,22 @@
From f84cd22a921c25c56a6c194d4825dbd9ceea0e5f Mon Sep 17 00:00:00 2001
From: Bernd <bernd@eckenfels.net>
Date: Sat, 22 Mar 2025 00:17:10 +0100
Subject: [PATCH] Update proc.c; remove redundant null check (CodeQL #3) (#44)
---
lib/proc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/proc.c b/lib/proc.c
index ce85fd1..d51d09f 100644
--- a/lib/proc.c
+++ b/lib/proc.c
@@ -35,7 +35,7 @@ char *proc_gen_fmt(const char *name, int more, FILE * fh,...)
if (!strcmp(title, head)) {
strcat(format, va_arg(ap, char *));
title = va_arg(ap, char *);
- if (!title || !head)
+ if (!title)
break;
} else {
strcat(format, "%*s"); /* XXX */
@@ -0,0 +1,33 @@
package net-tools {
description = "the collection of base networking utilities for Linux";
anitya = 10231;
version# = "2.10";
source = remoteTar {
url = "https://downloads.sourceforge.net/project/net-tools/"+
"net-tools-"+version+".tar.xz";
compress = xz;
checksum = "YLmSUeHOYnhYhjvnisX6MQNkPJRzOIgSZBHRiWmBdzzziWYJVY6hOpM8eWnAZ11N";
};
patches = [
"CVE-2025-46836.patch",
"GHSA-h667-qrp8-gj58.patch",
"f84cd22a921c25c56a6c194d4825dbd9ceea0e5f.patch",
"GHSA-w7jq-cmw2-cq59.patch",
];
enterSource = true;
writable = true;
exec = make {
chdir = false;
configureName = "(set +o pipefail && yes '' | make config)";
check = nil;
};
inputs = [
bash,
kernel-headers,
];
}
+2 -2
View File
@@ -50,7 +50,7 @@ package libnftnl {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
libmnl,
kernel-headers,
@@ -95,7 +95,7 @@ chmod +w /etc/ && ln -s ../usr/src/iptables/etc/ethertypes /etc/
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
bash,
python,
+1 -1
View File
@@ -12,7 +12,7 @@ package noto {
enterSource = true;
exec = generic {
inPlace = true;
chdir = false;
install = `
DEST=/work/system/share/fonts/noto
for font in $(ls -d fonts/*/); do
+7 -8
View File
@@ -17,7 +17,7 @@ package nss {
website = "https://firefox-source-docs.mozilla.org/security/nss/index.html";
anitya = 2503;
version# = "3.126";
version# = "3.126.1";
source = remoteGitHub {
suffix = "nss-dev/nss";
tag = "NSS_"+join {
@@ -28,7 +28,7 @@ package nss {
};
sep = "_";
}+"_RTM";
checksum = "gzMK4RkCHhgmhe33imV0qzZ8e2_VFAsF5M2db-1jrCWzh6XGijm51P2DIdDO2Dsf";
checksum = "3J7o7P3KlE8Cen4fzHLwvDKA1rrcJ84yBTniJHcIBw59LPT-7Q0NxL2CC4BKGW3F";
};
extra = [ nspr ];
@@ -38,10 +38,9 @@ package nss {
early = "\nln -s extra/nspr/nspr /usr/src/nspr\nchmod +w ../nspr/\n";
exec = make {
omitDefaults = true;
skipConfigure = true;
inPlace = true;
defaults = false;
chdir = false;
configure = nil;
make = [
"CCC=clang++",
"NSDISTMODE=copy",
@@ -49,7 +48,7 @@ package nss {
"USE_64=1",
"nss_build_all",
];
skipCheck = true;
check = nil;
install = `
cp -r \
/usr/src/dist/. \
@@ -80,7 +79,7 @@ package nss-cacert {
enterSource = true;
exec = generic {
inPlace = true;
chdir = false;
build = `
mkdir -p /work/system/etc/ssl/{certs/unbundled,certs/hashed,trust-source}
buildcatrust \
+1 -1
View File
@@ -21,7 +21,7 @@ package openssl {
];
exec = make {
omitDefaults = true;
defaults = false;
configureName = "/usr/src/openssl/Configure";
configure = {
+1 -1
View File
@@ -18,7 +18,7 @@ package pango {
"cairo": "enabled";
};
// Fontconfig error: Cannot load default config file: File not found: /etc/fonts/fonts.conf
skipTest = true;
test = false;
};
inputs = [
+3 -3
View File
@@ -28,8 +28,8 @@ disable_test ext/POSIX/t/time.t
toyboxEarly = true;
exec = make {
omitDefaults = true;
inPlace = true;
defaults = false;
chdir = false;
configureName = "./Configure";
configure = {
@@ -70,7 +70,7 @@ package perl-Module-Build {
chmod = true;
exec = generic {
inPlace = true;
chdir = false;
build = `
perl Build.PL --prefix=/system
./Build build`;
+16
View File
@@ -0,0 +1,16 @@
package pkgconf {
description = "package compiler and linker metadata toolkit";
website = "https://github.com/pkgconf/pkgconf";
anitya = 12753;
version# = "3.0.5";
source = remoteGitHub {
suffix = "pkgconf/pkgconf";
tag = "pkgconf-"+version;
checksum = "ZWak6fggXCzZkROSnSrl9twRRV9OJA7Q4DamFKEm094e2vgf_99gCxkmrZP3VFYH";
};
exec = meson {
postInstall = "ln -s pkgconf /work/system/bin/pkg-config";
};
}
+3 -3
View File
@@ -3,12 +3,12 @@ package procps {
website = "https://gitlab.com/procps-ng/procps";
anitya = 3708;
version# = "4.0.6";
version# = "4.0.7";
source = remoteGitLab {
domain = "gitlab.com";
suffix = "procps-ng/procps";
ref = "v"+version;
checksum = "pl_fZLvDlv6iZTkm8l_tHFpzTDVFGCiSJEs3eu0zAX6u36AV36P_En8K7JPScRWM";
checksum = "h5d0Wd_YyDzeRyduE4YawF0edvyMWA3UBcAXWAMg2fdtHhl5i1r0QeDu1-xAyR8g";
};
exec = make {
@@ -24,6 +24,6 @@ package procps {
libtool,
gzip,
pkg-config,
pkgconf,
];
}
+61 -18
View File
@@ -3,6 +3,9 @@ package python {
website = "https://www.python.org";
anitya = 13254;
// too many inputs; early variant available
bootstrap = false;
version# = "3.14.7";
source = remoteTar {
url = "https://www.python.org/ftp/python/"+version+
@@ -148,18 +151,18 @@ package python-setuptools {
website = "https://pypi.org/project/setuptools";
anitya = 4021;
version# = "83.0.0";
version# = "84.0.0";
source = remoteGitHub {
suffix = "pypa/setuptools";
tag = "v"+version;
checksum = "WqYSqCAvwpcIG6yXV8vVzRMNWl2CrcPOUPwlYrLV70ykHSpKxW1-XYQ4Z4n0ebAt";
checksum = "K9PGFv7ju_v4sykQCcROCc8Zdz3TfxYv95JlKFGXUnpf1yqRZW3oA0LuUQfE2x8n";
};
exec = pip {
// error: invalid command 'dist_info'
buildIsolation = true;
// pytest circular dependency
skipCheck = true;
check = nil;
};
runtime = [ python ];
@@ -170,11 +173,11 @@ package python-wheel {
website = "https://peps.python.org/pep-0427";
anitya = 11428;
version# = "0.47.0";
version# = "0.48.0";
source = remoteGitHub {
suffix = "pypa/wheel";
tag = version;
checksum = "HZ-MvkUP8mbbx2YmsRNswj_bbOCIiXckuHqL5Qbvb5NxN5DYfWnqwkGNyS7OrId0";
checksum = "h-UZQHS-NwB3b9YxYpJePR5cbDGZaKxz4bdhYjilWdQXAE46SV7A1CwZKzZcuZFh";
};
exec = pip {
@@ -209,7 +212,7 @@ package python-vcs-versioning {
// upstream is monorepo of two packages (setuptools-scm)
append = [ "vcs-versioning" ];
// pytest circular dependency
skipCheck = true;
check = nil;
};
inputs = [
@@ -243,7 +246,7 @@ package python-setuptools-scm {
// upstream is monorepo of two packages
append = [ "setuptools-scm" ];
// pytest circular dependency
skipCheck = true;
check = nil;
};
inputs = [
@@ -273,7 +276,7 @@ package python-flit-core {
// upstream has other unused packages with many dependencies
append = [ "flit_core" ];
// pytest circular dependency
skipCheck = true;
check = nil;
};
runtime = [ python ];
@@ -293,7 +296,7 @@ package python-packaging {
exec = pip {
// pytest circular dependency
skipCheck = true;
check = nil;
};
inputs = [ python-flit-core ];
@@ -314,7 +317,7 @@ package python-pathspec {
exec = pip {
// pytest circular dependency
skipCheck = true;
check = nil;
};
inputs = [ python-flit-core ];
@@ -335,7 +338,7 @@ package python-trove-classifiers {
exec = pip {
// pytest circular dependency
skipCheck = true;
check = nil;
};
inputs = [ python-setuptools ];
@@ -360,30 +363,68 @@ package python-pluggy {
exec = pip {
// pytest circular dependency
skipCheck = true;
check = nil;
};
inputs = [ python-setuptools-scm ];
runtime = [ python ];
}
package python-poetry-core {
description = "poetry PEP 517 Build Backend & Core Utilities";
website = "https://github.com/python-poetry/poetry-core";
anitya = 71155;
version# = "2.4.1";
source = remoteGitHub {
suffix = "python-poetry/poetry-core";
tag = version;
checksum = "tf9OeSUv9TJwKd48fQIU2uGtZ36GN-PDmPDZzjClozzLjv-rQ5nIbOg9gOXpegiH";
};
exec = pip {
// pytest circular dependency
check = nil;
};
}
package python-tomlkit {
description = "style-preserving TOML library for Python";
website = "https://github.com/python-poetry/tomlkit";
anitya = 19609;
version# = "0.15.1";
source = remoteGitHub {
suffix = "python-poetry/tomlkit";
tag = version;
checksum = "6n8h0Yf-OO0ARildxqyB1mB1EhS7uALtqFJqD7t7G1JSFTTb9RGRWSpCg-vamuu8";
};
exec = pip {
// pytest circular dependency
check = nil;
};
inputs = [ python-poetry-core ];
}
package python-hatchling {
description = "the extensible, standards compliant build backend used by Hatch";
website = "https://hatch.pypa.io";
anitya = 16137;
version# = "1.17.1";
version# = "1.18.0";
source = remoteGitHub {
suffix = "pypa/hatch";
tag = "hatch-v"+version;
checksum = "FK9PkGIkL3wyVFHOKrx9lSRqoevuQ_TFrN-pMqsoFKsh5eim4pfzx7MvL3ioif9o";
checksum = "a_ntndxBlMdqSVW3PkiAY42m-NDgyWJcKLWFIVTB_5PciVeJdYYdbcdF6jsd0U96";
};
exec = pip {
// upstream has other unused packages with many dependencies
append = [ "backend" ];
// pytest circular dependency
skipCheck = true;
check = nil;
};
inputs = [
@@ -391,6 +432,7 @@ package python-hatchling {
python-pathspec,
python-trove-classifiers,
python-pluggy,
python-tomlkit,
];
runtime = [
@@ -398,6 +440,7 @@ package python-hatchling {
python-pathspec,
python-trove-classifiers,
python-pluggy,
python-tomlkit,
];
}
@@ -415,7 +458,7 @@ package python-pygments {
exec = pip {
// pytest circular dependency
skipCheck = true;
check = nil;
};
inputs = [ python-hatchling ];
@@ -440,7 +483,7 @@ package python-iniconfig {
exec = pip {
// pytest circular dependency
skipCheck = true;
check = nil;
};
inputs = [ python-setuptools-scm ];
@@ -465,7 +508,7 @@ package python-pytest {
exec = pip {
// many dependencies
skipCheck = true;
check = nil;
};
inputs = [
@@ -0,0 +1,12 @@
diff --git a/tests/qemu-iotests/tests/copy-before-write b/tests/qemu-iotests/tests/copy-before-write
index 236cb8ac37..0eac14005e 100755
--- a/tests/qemu-iotests/tests/copy-before-write
+++ b/tests/qemu-iotests/tests/copy-before-write
@@ -279,6 +279,7 @@ read 1048576/1048576 bytes at offset 0
return log
def test_timeout_break_guest(self):
+ return
log = self.do_cbw_timeout('break-guest-write')
# macOS and FreeBSD tend to represent ETIMEDOUT as
# "Operation timed out", when Linux prefer
@@ -0,0 +1,16 @@
diff --git a/tests/qemu-iotests/150 b/tests/qemu-iotests/150
index fab0faa389..d71fb5978d 100755
--- a/tests/qemu-iotests/150
+++ b/tests/qemu-iotests/150
@@ -41,6 +41,11 @@ _supported_fmt raw qcow2
_supported_proto file
_supported_os Linux
+# work directory is never an overlay
+if [ "$(stat -fc '%T' /work/)" = "zfs" ]; then
+ _notrun 'fails on zfs'
+fi
+
img_size=1048576
@@ -0,0 +1,13 @@
diff --git a/configure b/configure
index 6ddfe4b534..1cba33d562 100755
--- a/configure
+++ b/configure
@@ -1946,7 +1946,7 @@ if test "$skip_meson" = no; then
test -n "$gdb_bin" && meson_option_add "-Dgdb=$gdb_bin"
run_meson() {
- NINJA=$ninja $meson setup "$@" "$PWD" "$source_path"
+ NINJA=$ninja CLICOLOR_FORCE=1 $meson setup "$@" "$PWD" "$source_path"
}
eval run_meson $meson_options
if test "$?" -ne 0 ; then
+11 -8
View File
@@ -3,16 +3,22 @@ package qemu {
website = "https://www.qemu.org";
anitya = 13607;
version# = "11.0.3";
version# = "11.1.0";
source = remoteTar {
url = "https://download.qemu.org/qemu-"+version+".tar.bz2";
checksum = "cY1nZe92-WGeOErkkEXU0pDidJxBFgF4JCtUv1IJk0qVUYHw3VSZfVms1NqWfTLq";
checksum = "nOjPiAFhPGVBnM2rYokJhMDUhFM_6ec-B2N-1-LB1wmCiLzF5_ppqSgkNESuoBFu";
compress = bzip2;
};
patches = [
"meson-colour.patch",
"iotests-zfs.patch",
"disable-mcast-test.patch",
// fails with ipv6 disabled
"disable-netdev-socket.patch",
// fails on a slower machine
"copy-before-write-spurious.patch",
];
// configure script uses source as scratch space
@@ -29,10 +35,6 @@ sed -i \
tests/qemu-iotests/[0-9][0-9][0-9]* \
tests/qemu-iotests/tests/copy-before-write \
tests/qemu-iotests/tests/file-io-error.out
cat << EOF > tests/qemu-iotests/150
#!/bin/sh
_notrun 'appears to spuriously fail on zfs'
EOF
`;
exec = make {
@@ -56,16 +58,17 @@ EOF
check = [
"TIMEOUT_MULTIPLIER=5",
"check",
];
};
inputs = [
bash,
python,
python-setuptools,
python-wheel,
meson,
ninja,
pkg-config,
pkgconf,
diffutils,
openssl,
+3 -2
View File
@@ -15,7 +15,8 @@ package rsync {
toyboxEarly = true;
exec = make {
omitDefaults = true;
defaults = false;
configure = {
"disable-openssl";
"disable-xxhash";
@@ -24,6 +25,6 @@ package rsync {
};
// circular dependency
skipCheck = true;
check = nil;
};
}
+1 -1
View File
@@ -14,7 +14,7 @@ package spirv-headers {
exec = cmake {
// upstream has no tests
skipTest = true;
test = nil;
};
}
+3 -4
View File
@@ -28,10 +28,9 @@ package squashfs-tools {
early = "cd squashfs-tools";
exec = make {
skipConfigure = true;
inPlace = true;
skipCheck = true;
chdir = false;
configure = nil;
check = nil;
install = "make INSTALL_PREFIX=/work/system install";
};
+1 -1
View File
@@ -19,7 +19,7 @@ package tamago {
enterSource = true;
exec = generic {
inPlace = true;
chdir = false;
build = `
mkdir /work/system/
cp -r . /work/system/tamago
+8 -8
View File
@@ -22,10 +22,10 @@ package toybox {
toyboxEarly = true;
exec = make {
omitDefaults = true;
inPlace = true;
skipConfigure = true;
defaults = false;
chdir = false;
configure = nil;
preMake = `
LDFLAGS="${LDFLAGS:-''} -static"
@@ -50,7 +50,7 @@ sed -i \
"USER=cure",
"tests",
];
skipEarlyStageCheck = true;
checkEarly = false;
install = "PREFIX=/work/system/bin make install_flat";
@@ -80,10 +80,10 @@ package toybox-early {
toyboxEarly = true;
exec = make {
omitDefaults = true;
inPlace = true;
skipConfigure = true;
defaults = false;
chdir = false;
configure = nil;
preMake = `
LDFLAGS="${LDFLAGS:-''} -static"
@@ -115,7 +115,7 @@ CONFIG_DIFF=y
"USER=cure",
"tests",
];
skipEarlyStageCheck = true;
checkEarly = false;
install = "PREFIX=/work/system/bin make install_flat";
+1 -1
View File
@@ -20,7 +20,7 @@ package unzip {
chmod = true;
exec = generic {
inPlace = true;
chdir = false;
build = `unix/configure
make -f unix/Makefile generic1`;
install = `
+1 -1
View File
@@ -47,7 +47,7 @@ package util-linux {
// check script claims:
// For development purpose only.
// Don't execute on production system!
skipCheck = true;
check = nil;
};
inputs = [
+2 -2
View File
@@ -17,14 +17,14 @@ package vim {
enterSource = true;
exec = make {
inPlace = true;
chdir = false;
configure = {
"with-tlib": "ncursesw";
};
check = [ "test" ];
// very expensive
skipCheck = true;
check = nil;
};
inputs = [ ncurses ];
+20 -20
View File
@@ -34,7 +34,7 @@ package libxtrans {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
];
@@ -59,7 +59,7 @@ package xorgproto {
inputs = [
automake,
pkg-config,
pkgconf,
util-macros,
];
@@ -121,7 +121,7 @@ package xcb {
inputs = [
python,
pkg-config,
pkgconf,
xcb-proto,
libXau,
@@ -148,7 +148,7 @@ package libxcb-keysyms {
exec = make {};
inputs = [
pkg-config,
pkgconf,
xcb,
];
@@ -172,7 +172,7 @@ package libxcb-wm {
inputs = [
m4,
pkg-config,
pkgconf,
xcb,
];
@@ -196,7 +196,7 @@ package libxcb-util {
exec = make {};
inputs = [
pkg-config,
pkgconf,
util-macros,
xcb,
@@ -220,7 +220,7 @@ package libxcb-image {
exec = make {};
inputs = [
pkg-config,
pkgconf,
libxcb-util,
];
@@ -244,7 +244,7 @@ package libxcb-render-util {
exec = make {};
inputs = [
pkg-config,
pkgconf,
util-macros,
xcb,
@@ -278,7 +278,7 @@ package libX11 {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
libxtrans,
@@ -309,7 +309,7 @@ package libXext {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
libX11,
@@ -338,7 +338,7 @@ package libXfixes {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
xorgproto,
@@ -368,7 +368,7 @@ package libXrender {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
libX11,
@@ -397,7 +397,7 @@ package libxshmfence {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
xorgproto,
@@ -424,7 +424,7 @@ package libXxf86vm {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
libXext,
@@ -454,7 +454,7 @@ package libXrandr {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
libXext,
@@ -488,7 +488,7 @@ package font-util {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
];
@@ -514,7 +514,7 @@ package libfontenc {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
font-util,
@@ -561,7 +561,7 @@ package xkbcomp {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
byacc,
util-macros,
@@ -591,7 +591,7 @@ package libXfont2 {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
freetype,
@@ -642,7 +642,7 @@ package libXdmcp {
inputs = [
automake,
libtool,
pkg-config,
pkgconf,
util-macros,
xorgproto,
+14
View File
@@ -320,6 +320,8 @@ type PackageAttr struct {
// Whether to replace /usr/bin/ with a symlink to /bin/.
PopulateUsrBin bool
// Whether this package is disallowed from bootstrap stages.
Std bool
// Hint for an early variant of toybox to be used when available.
Early bool
// Whether to omit output colour environment variables.
@@ -375,6 +377,14 @@ func (t Toolchain) Append(a []pkg.Artifact, handles ...ArtifactH) []pkg.Artifact
return a
}
// A BootstrapError describes a package disallowed from bootstrap stages.
type BootstrapError string
func (e BootstrapError) Error() string {
return "package " + strconv.Quote(string(e)) +
" must not be built by bootstrap stages"
}
// New constructs a [pkg.Artifact] via a build system helper.
func (t Toolchain) New(
name, version string,
@@ -387,6 +397,10 @@ func (t Toolchain) New(
attr = new(PackageAttr)
}
if attr.Std && !t.stage.isStd() {
panic(BootstrapError(name))
}
if name == "" || version == "" {
panic("name must be non-empty")
}
+46 -12
View File
@@ -811,14 +811,17 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs,
) (v any, set bool, err error) {
var attr GenericHelper
chdir := true
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("inPlace"): &attr.InPlace,
k("chdir"): &chdir,
k("build"): &attr.Build,
k("check"): &attr.Check,
k("install"): &attr.Install,
}); err != nil {
return
}
attr.InPlace = !chdir
v = &attr
set = true
return
@@ -828,28 +831,33 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs,
) (v any, set bool, err error) {
var attr MakeHelper
defaults, chdir, checkEarly := true, true, true
attr.Configure, attr.Check = []KV{}, []string{}
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("omitDefaults"): &attr.OmitDefaults,
k("defaults"): &defaults,
k("generate"): &attr.Generate,
k("preMake"): &attr.ScriptMakeEarly,
k("preCheck"): &attr.ScriptCheckEarly,
k("postInstall"): &attr.Script,
k("inPlace"): &attr.InPlace,
k("skipConfigure"): &attr.SkipConfigure,
k("chdir"): &chdir,
k("configureName"): &attr.ConfigureName,
k("forceAutoconf"): &attr.ForceAutoconf,
k("configure"): &attr.Configure,
k("host"): &attr.Host,
k("build"): &attr.Build,
k("make"): &attr.Make,
k("skipCheck"): &attr.SkipCheck,
k("check"): &attr.Check,
k("install"): &attr.Install,
k("skipEarlyStageCheck"): &attr.SkipCheckEarly,
k("checkEarly"): &checkEarly,
}); err != nil {
return
}
attr.OmitDefaults, attr.InPlace = !defaults, !chdir
attr.SkipConfigure = attr.Configure == nil
attr.SkipCheck = attr.Check == nil
attr.SkipCheckEarly = !checkEarly
v = &attr
set = true
return
@@ -859,17 +867,20 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs,
) (v any, set bool, err error) {
var attr CMakeHelper
var test azalea.AString
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("append"): &attr.Append,
k("buildType"): &attr.BuildType,
k("cache"): &attr.Cache,
k("postInstall"): &attr.Script,
k("test"): &attr.Test,
k("skipTest"): &attr.SkipTest,
k("test"): &test,
k("make"): &attr.Make,
}); err != nil {
return
}
attr.Test = test.V
attr.SkipTest = test.Nil
v = &attr
set = true
return
@@ -879,18 +890,21 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs,
) (v any, set bool, err error) {
var attr MesonHelper
test := true
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("muon"): &attr.Muon,
k("preCompile"): &attr.ScriptCompileEarly,
k("postCompile"): &attr.ScriptCompiled,
k("postInstall"): &attr.Script,
k("setup"): &attr.Setup,
k("skipTest"): &attr.SkipTest,
k("test"): &test,
k("skipTests"): &attr.SkipTests,
k("interactiveTest"): &attr.InteractiveTest,
}); err != nil {
return
}
attr.SkipTest = !test
v = &attr
set = true
return
@@ -900,11 +914,13 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs,
) (v any, set bool, err error) {
var attr MakeMakerHelper
doCheck := true
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("skipCheck"): &attr.SkipCheck,
k("check"): &doCheck,
}); err != nil {
return
}
attr.SkipCheck = !doCheck
v = &attr
set = true
return
@@ -914,17 +930,20 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs,
) (v any, set bool, err error) {
var attr PipHelper
var scriptCheck azalea.AString
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("append"): &attr.Append,
k("buildIsolation"): &attr.BuildIsolation,
k("enterSource"): &attr.EnterSource,
k("install"): &attr.Install,
k("skipCheck"): &attr.SkipCheck,
k("check"): &attr.Check,
k("check"): &scriptCheck,
k("postInstall"): &attr.Script,
}); err != nil {
return
}
attr.Check = scriptCheck.V
attr.SkipCheck = scriptCheck.Nil
v = &attr
set = true
return
@@ -975,6 +994,13 @@ type evalContext struct {
t Toolchain
}
// HelperError describes a package with nil helper.
type HelperError string
func (e HelperError) Error() string {
return "package " + strconv.Quote(string(e)) + " has no exec helper"
}
// pf implements [azalea.PF].
func (ctx *evalContext) pf(
name azalea.Ident,
@@ -998,6 +1024,8 @@ func (ctx *evalContext) pf(
overlay string
inputs, runtimes, extra azalea.Array
bootstrap = true
)
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("description"): &meta.Description,
@@ -1020,6 +1048,7 @@ func (ctx *evalContext) pf(
k("exclusive"): &attr.Exclusive,
k("toyboxEarly"): &attr.Early,
k("minimal"): &attr.NoToolchain,
k("bootstrap"): &bootstrap,
k("checksum"): &kc,
k("output"): &output,
@@ -1032,6 +1061,7 @@ func (ctx *evalContext) pf(
}); err != nil {
return
}
attr.Std = !bootstrap
var inputsH, extraH P
if inputsH, err = toHandles(inputs); err != nil {
return
@@ -1149,6 +1179,10 @@ func (ctx *evalContext) pf(
}
}
if helper == nil {
panic(HelperError(name))
}
v = cachedArtifact{&meta, ctx.t.New(
meta.Name,
meta.Version,