Compare commits

...
33 Commits
Author SHA1 Message Date
cat 88a19aefaa internal/rosa/package/python: 3.14.7 to 3.15.0
This has been blocking OpenSSL for months. This currently sits on a release candidate.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-15 18:10:22 +09:00
cat f01776200d internal/rosa/package/openssl: 3.6.2 to 4.0.1
Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-08-15 18:09:23 +09:00
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
91 changed files with 943 additions and 585 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' 'files:files:__hakurei_files'
} }
_hakurei_kill() {
_alternative \
'instances:domains:__hakurei_instances'
}
__hakurei_files() { __hakurei_files() {
_files -g "*.(json|hakurei)" _files -g "*.(json|hakurei)"
return $? return $?
@@ -60,6 +65,7 @@ __hakurei_instances() {
"run:Load and start container from configuration file" "run:Load and start container from configuration file"
"exec:Configure and start a permissive container" "exec:Configure and start a permissive container"
"show:Show live or local instance configuration" "show:Show live or local instance configuration"
"kill:Terminate an active instance"
"ps:List active instances" "ps:List active instances"
"version:Display version information" "version:Display version information"
"license:Show full license text" "license:Show full license text"
+2 -2
View File
@@ -217,7 +217,7 @@ func main() {
mustWriteFile("comp/", nil, os.ModeDir|0755) mustWriteFile("comp/", nil, os.ModeDir|0755)
mustWriteFile("comp/_hakurei", comp, 0644) mustWriteFile("comp/_hakurei", comp, 0644)
mustWriteFile("install.sh", []byte(`#!/bin/sh -e 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/hakurei" "${DESTDIR}`+prefix+`/bin/hakurei"
install -vDm0755 "bin/sharefs" "${DESTDIR}`+prefix+`/bin/sharefs" install -vDm0755 "bin/sharefs" "${DESTDIR}`+prefix+`/bin/sharefs"
@@ -230,7 +230,7 @@ fi
install -vDm0644 "comp/_hakurei" "${DESTDIR}`+prefix+`/share/zsh/site-functions/_hakurei" install -vDm0644 "comp/_hakurei" "${DESTDIR}`+prefix+`/share/zsh/site-functions/_hakurei"
`), 0755) `), 0755)
mustWriteFromPath("README.md", "README.md", 0) mustWriteFromPath("LICENSE", "LICENSE", 0)
mustWriteFile("hsurc.default", []byte("1000 0"), 0400) mustWriteFile("hsurc.default", []byte("1000 0"), 0400)
mustWriteFromPath("bin/hsu", filepath.Join(s, "hsu"), 04511) mustWriteFromPath("bin/hsu", filepath.Join(s, "hsu"), 04511)
for _, name := range []string{ for _, name := range []string{
+18
View File
@@ -11,6 +11,7 @@ import (
"os/user" "os/user"
"strconv" "strconv"
"sync" "sync"
"syscall"
"time" "time"
"hakurei.app/check" "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") 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 var flagShort bool
c.NewCommand("ps", "List active instances", func(args []string) error { 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 run Load and start container from configuration file
exec Configure and start a permissive container exec Configure and start a permissive container
show Show live or local instance configuration show Show live or local instance configuration
kill Terminate an active instance
ps List active instances ps List active instances
version Display version information version Display version information
license Show full license text license Show full license text
+4
View File
@@ -1196,6 +1196,10 @@ func main() {
if w, ok := err.(interface{ Unwrap() []error }); !ok { if w, ok := err.(interface{ Unwrap() []error }); !ok {
log.Fatal(err) log.Fatal(err)
} else { } else {
if _, ok = w.(pkg.InputError); ok {
log.Fatal(w)
}
errs := w.Unwrap() errs := w.Unwrap()
for i, e := range errs { for i, e := range errs {
if i == len(errs)-1 { if i == len(errs)-1 {
+2 -5
View File
@@ -118,11 +118,8 @@ func TestExec(t *testing.T) {
[]string{"testtool"}, []string{"testtool"},
pkg.MustPath("/proc/nonexistent", false, failingArtifact), pkg.MustPath("/proc/nonexistent", false, failingArtifact),
), nil, nil, pkg.WNew, &pkg.DependencyCureError{ ), nil, nil, pkg.WNew, pkg.InputError{
{ failingArtifact: stub.UniqueError(0xcafe),
A: failingArtifact,
Err: stub.UniqueError(0xcafe),
},
}}, }},
{"invalid paths", pkg.NewExec( {"invalid paths", pkg.NewExec(
+47 -91
View File
@@ -15,10 +15,10 @@ import (
"hash" "hash"
"io" "io"
"io/fs" "io/fs"
"iter"
"maps" "maps"
"math" "math"
"os" "os"
"os/signal"
"path/filepath" "path/filepath"
"runtime" "runtime"
"slices" "slices"
@@ -654,10 +654,10 @@ type pendingArtifactDep struct {
// if curing succeeds. // if curing succeeds.
resP *cureRes 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, // after acquiring errsMu if curing fails. No additional action is taken,
// [Cache] and its caller are responsible for further error handling. // [Cache] and its caller are responsible for further error handling.
errs *DependencyCureError errs InputError
// Address of mutex synchronising access to errs. // Address of mutex synchronising access to errs.
errsMu *sync.Mutex errsMu *sync.Mutex
@@ -1721,109 +1721,61 @@ retry:
goto retry goto retry
} }
// CureError wraps a non-nil error returned attempting to cure an [Artifact]. // An InputError describes inputs of a [FloodArtifact] which had failed to cure.
type CureError struct { type InputError map[Artifact]error
A Artifact
Err error
}
// Unwrap returns the underlying error. // unwrap returns an iterator over sorted, deduplicated [Artifact] and their
func (e *CureError) Unwrap() error { return e.Err } // corresponding identifier.
func (e InputError) unwrap() iter.Seq2[Artifact, unique.Handle[ID]] {
ir := NewIR()
// Error returns the error message from the underlying Err. type input struct {
func (e *CureError) Error() string { return e.Err.Error() } a Artifact
// 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
}
}
// 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] id unique.Handle[ID]
err *CureError
} }
errs := make([]*ent, 0, len(me)) p := make([]input, 0, len(e))
for id, err := range me { for a := range e {
errs = append(errs, &ent{id, err}) p = append(p, input{a, ir.Ident(a)})
} }
var identBuf [2]ID 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() identBuf[0], identBuf[1] = a.id.Value(), b.id.Value()
return slices.Compare(identBuf[0][:], identBuf[1][:]) 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)) return func(yield func(Artifact, unique.Handle[ID]) bool) {
for i, v := range errs { for _, i := range p {
_errs[i] = v.err if !yield(i.a, i.id) {
return
}
}
} }
return _errs
} }
// Unwrap returns a deduplicated slice of underlying errors. // Error returns a user-facing, deterministic text representation of e.
func (e *DependencyCureError) Unwrap() []error { func (e InputError) Error() string {
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"
}
var buf strings.Builder var buf strings.Builder
buf.WriteString("errors curing dependencies:") buf.WriteString("errors curing inputs:")
for _, err := range errs { for a, id := range e.unwrap() {
buf.WriteString("\n\t" + buf.WriteString("\n\t")
reportName(err.A, ir.Ident(err.A)) + ": " + buf.WriteString(reportName(a, id))
err.Error()) buf.WriteString(": ")
} buf.WriteString(e[a].Error())
if ctx.Err() != nil {
buf.WriteString("\nerror resolution cancelled")
} }
return buf.String() 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. // enterCure must be called before entering an [Artifact] implementation.
func (c *Cache) enterCure(a Artifact, curesExempt bool) error { func (c *Cache) enterCure(a Artifact, curesExempt bool) error {
if c.attr.Notify != nil { if c.attr.Notify != nil {
@@ -2023,7 +1975,7 @@ func (c *Cache) cureMany(
wg.Add(len(inputs)) wg.Add(len(inputs))
var mask []bool var mask []bool
res := make([]cureRes, len(inputs)) res := make([]cureRes, len(inputs))
errs := make(DependencyCureError, 0, len(inputs)) errs := make(InputError)
var errsMu sync.Mutex var errsMu sync.Mutex
if shallow { if shallow {
mask = make([]bool, len(inputs)) mask = make([]bool, len(inputs))
@@ -2042,13 +1994,13 @@ func (c *Cache) cureMany(
continue continue
} }
} }
pending := pendingArtifactDep{d, &res[i], &errs, &errsMu, &wg} pending := pendingArtifactDep{d, &res[i], errs, &errsMu, &wg}
go pending.cure(c) go pending.cure(c)
} }
wg.Wait() wg.Wait()
if len(errs) > 0 { if len(errs) > 0 {
return mask, &errs return mask, errs
} }
for i, p := range res { for i, p := range res {
if shallow && mask[i] { if shallow && mask[i] {
@@ -2651,7 +2603,11 @@ func (pending *pendingArtifactDep) cure(c *Cache) {
} }
pending.errsMu.Lock() 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() pending.errsMu.Unlock()
} }
+32 -49
View File
@@ -861,14 +861,11 @@ func TestCache(t *testing.T) {
cure: func(f *pkg.FContext) error { cure: func(f *pkg.FContext) error {
panic("attempting to cure impossible artifact") panic("attempting to cure impossible artifact")
}, },
}, nil, nil, pkg.WNew, &pkg.DependencyCureError{ }, nil, nil, pkg.WNew, pkg.InputError{
{ failingFile: struct {
A: failingFile,
Err: struct {
_ []byte _ []byte
stub.UniqueError stub.UniqueError
}{UniqueError: 0xbad}, }{UniqueError: 0xbad},
},
}}, }},
}) })
@@ -1949,7 +1946,7 @@ errors during scrub:
} }
} }
func TestDependencyCureError(t *testing.T) { func TestInputError(t *testing.T) {
t.Parallel() t.Parallel()
makeIdent := func(ident ...byte) pkg.Artifact { makeIdent := func(ident ...byte) pkg.Artifact {
@@ -1962,56 +1959,40 @@ func TestDependencyCureError(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
err pkg.DependencyCureError err pkg.InputError
want string want string
unwrap []error unwrap []error
}{ }{
{"simple", pkg.DependencyCureError{ {"simple", pkg.InputError{
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)}, makeIdent(0xff, 9): stub.UniqueError(0xbad09),
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)}, makeIdent(0xff, 0): stub.UniqueError(0xbad00),
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)}, makeIdent(0xff, 0xf): stub.UniqueError(0xbad0f),
{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)}, makeIdent(0xff, 1): stub.UniqueError(0xbad01),
}, `errors curing dependencies: }, `errors curing inputs:
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite _wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite _wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite _wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{ _w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{
&pkg.CureError{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)}, stub.UniqueError(0xbad00),
&pkg.CureError{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)}, stub.UniqueError(0xbad01),
&pkg.CureError{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)}, stub.UniqueError(0xbad09),
&pkg.CureError{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)}, stub.UniqueError(0xbad0f),
}}, }},
{"dedup", pkg.DependencyCureError{ {"dedup", pkg.InputError{
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)}, makeIdent(0xff, 9): stub.UniqueError(0xbad09),
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)}, makeIdent(0xff, 9): stub.UniqueError(0xbad09),
{A: makeIdent(0xff, 0xfd), Err: &pkg.DependencyCureError{ makeIdent(0xff, 9): stub.UniqueError(0xbad09),
{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)}, makeIdent(0xff, 0): stub.UniqueError(0xbad00),
{A: makeIdent(0xff, 0xc), Err: &pkg.DependencyCureError{ makeIdent(0xff, 0): stub.UniqueError(0xbad00),
{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)}, makeIdent(0xff, 1): stub.UniqueError(0xbad01),
{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)}, }, `errors curing inputs:
}},
{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:
_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite _wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765184 injected by the test suite
_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite _wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765185 injected by the test suite
_wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite _wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765193 injected by the test suite`, []error{
_w8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA: unique error 765199 injected by the test suite`, []error{ stub.UniqueError(0xbad00),
&pkg.CureError{A: makeIdent(0xff, 0), Err: stub.UniqueError(0xbad00)}, stub.UniqueError(0xbad01),
&pkg.CureError{A: makeIdent(0xff, 1), Err: stub.UniqueError(0xbad01)}, stub.UniqueError(0xbad09),
&pkg.CureError{A: makeIdent(0xff, 9), Err: stub.UniqueError(0xbad09)},
&pkg.CureError{A: makeIdent(0xff, 0xf), Err: stub.UniqueError(0xbad0f)},
}}, }},
} }
for _, tc := range testCases { for _, tc := range testCases {
@@ -2055,19 +2036,21 @@ func (a earlyFailureF) Cure(*pkg.FContext) error {
func BenchmarkEarlyDCE(b *testing.B) { func BenchmarkEarlyDCE(b *testing.B) {
msg := message.New(log.New(os.Stderr, "dce: ", 0)) msg := message.New(log.New(os.Stderr, "dce: ", 0))
msg.SwapVerbose(testing.Verbose()) msg.SwapVerbose(testing.Verbose())
for b.Loop() {
b.StopTimer()
c, err := pkg.Open(b.Context(), msg, check.MustAbs(b.TempDir()), nil) c, err := pkg.Open(b.Context(), msg, check.MustAbs(b.TempDir()), nil)
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
b.StartTimer()
_, _, err = c.Cure(earlyFailureF(8)) _, _, err = c.Cure(earlyFailureF(8))
b.StopTimer()
if !errors.Is(err, stub.UniqueError(0xcafe)) { if !errors.Is(err, stub.UniqueError(0xcafe)) {
b.Fatalf("Cure: error = %v", err) b.Fatalf("Cure: error = %v", err)
} }
c.Close() c.Close()
dce := err.(*pkg.DependencyCureError) b.StartTimer()
for b.Loop() {
dce.Unwrap()
} }
} }
+59 -6
View File
@@ -12,7 +12,7 @@ import (
// Value are types supported by the language. // Value are types supported by the language.
type Value interface { type Value interface {
bool | int64 | string | []string | []int64 | [][2]string bool | int64 | string | []string | []int64 | [][2]string | Nil
} }
type ( type (
@@ -33,6 +33,29 @@ type (
F func(args FArgs) (v any, set bool, err error) F func(args FArgs) (v any, set bool, err error)
V map[unique.Handle[Ident]]any 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. // 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()) return UndefinedError(arg.K.Value())
} }
err := storeE(r, arg.V)
if err != nil { if err := storeE(r, arg.V); err != nil {
return err 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. // 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() 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) v := reflect.ValueOf(r)
pt, vt := pv.Type(), v.Type() if vt := v.Type(); !vt.AssignableTo(pt) {
if !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} return TypeError{vt, pt}
} }
pv.Set(v) pv.Set(v)
@@ -226,6 +276,9 @@ func evaluateAny(d PF, s []Frame, expr, rp any) bool {
case "false": case "false":
store(rp, false) store(rp, false)
return true return true
case "nil":
store(rp, Nil{})
return true
default: default:
return evaluateAny(d, s, v, rp) return evaluateAny(d, s, v, rp)
} }
+69 -5
View File
@@ -100,15 +100,79 @@ func TestEvaluate(t *testing.T) {
Err: UndefinedError("f"), Err: UndefinedError("f"),
}}, }},
{"error wrap deep", `f { v = nil; }`, makeStackCheck(func( {"error wrap deep", `f { v = nonexistent; }`, makeStackCheck(func(
FArgs, FArgs,
) (any, error) { ) (any, error) {
panic("unreachable") panic("unreachable")
}), "", EvaluationError{ }), "", EvaluationError{
Expr: Ident("nil"), Expr: Ident("nonexistent"),
Err: UndefinedError("nil"), 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{ {"common inputs", `package name { inputs, v = []; }`, nil, "", EvaluationError{
Expr: Func{ Expr: Func{
Ident: Ident("name"), Ident: Ident("name"),
@@ -214,8 +278,8 @@ func TestEvaluate(t *testing.T) {
} }
var errEquals bool var errEquals bool
if _, ok := errors.AsType[TypeError](err); ok { if e, ok := errors.AsType[TypeError](err); ok {
errEquals = errors.Is(err, tc.err) errEquals = e.Is(tc.err)
} else { } else {
errEquals = reflect.DeepEqual(err, tc.err) errEquals = reflect.DeepEqual(err, tc.err)
} }
+1 -1
View File
@@ -39,7 +39,7 @@ package acl {
exec = make { exec = make {
// makes assumptions about uid_map/gid_map // makes assumptions about uid_map/gid_map
skipCheck = true; check = nil;
}; };
inputs = [ attr, kernel-headers ]; inputs = [ attr, kernel-headers ];
+3 -3
View File
@@ -15,9 +15,9 @@ package awk {
chmod = true; chmod = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
inPlace = true; chdir = false;
skipConfigure = true; configure = nil;
make = [ "YACC='yacc -d -b awkgram'" ]; make = [ "YACC='yacc -d -b awkgram'" ];
preCheck = "install -vD a.out /system/bin/awk\n"; preCheck = "install -vD a.out /system/bin/awk\n";
install = "install -vD a.out /work/system/bin/awk"; install = "install -vD a.out /work/system/bin/awk";
+1 -1
View File
@@ -12,7 +12,7 @@ package bison {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
check = [ check = [
"TESTSUITEFLAGS=" + jobsFlagE + "' " + skipGNUTests { "TESTSUITEFLAGS=" + jobsFlagE + "' " + skipGNUTests {
tests = [ tests = [
+1 -1
View File
@@ -19,6 +19,6 @@ package byacc {
chmod = true; chmod = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
}; };
} }
+4 -7
View File
@@ -15,13 +15,10 @@ package bzip2 {
enterSource = true; enterSource = true;
exec = make { exec = make {
skipConfigure = true; chdir = false;
skipCheck = true; configure = nil;
inPlace = true; make = [ "CC=cc" ];
check = nil;
make = [
"CC=cc",
];
install = "make PREFIX=/work/system install"; 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 // runs the entire test suite in a single meson test
interactiveTest = true; interactiveTest = true;
// only works with specific dependency versions // only works with specific dependency versions
skipTest = true; test = false;
}; };
inputs = [ inputs = [
+1 -1
View File
@@ -20,7 +20,7 @@ package cmake {
chmod = true; chmod = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
configureName = "/usr/src/cmake/bootstrap"; configureName = "/usr/src/cmake/bootstrap";
configure = { configure = {
+1 -1
View File
@@ -19,7 +19,7 @@ package connman {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
dbus, dbus,
iptables, iptables,
+1 -1
View File
@@ -21,7 +21,7 @@ touch \
`; `;
exec = make { exec = make {
inPlace = true; chdir = false;
configureName = "../dist/configure"; configureName = "../dist/configure";
forceAutoconf = true; forceAutoconf = true;
configure = { configure = {
+2 -2
View File
@@ -41,11 +41,11 @@ package xdg-dbus-proxy {
website = "https://github.com/flatpak/xdg-dbus-proxy"; website = "https://github.com/flatpak/xdg-dbus-proxy";
anitya = 58434; anitya = 58434;
version# = "0.1.7"; version# = "0.1.8";
source = remoteGitHub { source = remoteGitHub {
suffix = "flatpak/xdg-dbus-proxy"; suffix = "flatpak/xdg-dbus-proxy";
tag = version; tag = version;
checksum = "UW5Pe-TP-XAaN-kTbxrkOQ7eYdmlAQlr2pdreLtPT0uwdAz-7rzDP8V_8PWuZBup"; checksum = "ygdW0EEvZ-_PJfnFTNoobITmRzqJecTinBsJd_iJQrRvzidwqESCjeNkB55smZ2y";
}; };
exec = meson { exec = meson {
+4 -4
View File
@@ -18,17 +18,17 @@ package elfutils {
]; ];
exec = make { exec = make {
// nonstandard glibc extension
skipCheck = true;
configure = { configure = {
"enable-deterministic-archives"; "enable-deterministic-archives";
}; };
// nonstandard glibc extension
check = nil;
}; };
inputs = [ inputs = [
m4, m4,
pkg-config, pkgconf,
zlib, zlib,
bzip2, 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"; website = "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git";
anitya = 141464; anitya = 141464;
version# = "20260622"; version# = "20260810";
source = remoteGitLab { source = remoteGitLab {
domain = "gitlab.com"; domain = "gitlab.com";
suffix = "kernel-firmware/linux-firmware"; suffix = "kernel-firmware/linux-firmware";
ref = version; ref = version;
checksum = "gpytkDM58EVjaUuryOekcekh_rWsfuv3S7LQxopHlNlVGmMsuqNwfug4BjgTgizE"; checksum = "XNUhz9QstaDKNegM3Bl0-TtZzpsvX7-E8WMnDCO7KBhBC6t_TxsdG05-ETdXynry";
}; };
// dedup creates temporary file // dedup creates temporary file
@@ -22,17 +22,17 @@ package firmware {
]; ];
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipConfigure = true; chdir = false;
inPlace = true;
configure = nil;
make = [ make = [
"DESTDIR=/work/system", "DESTDIR=/work/system",
"install-zst", "install-zst",
]; ];
// requires pre-commit // requires pre-commit
skipCheck = true; check = nil;
install = "make " + jobsFlagE + " " + loadFlagE + " DESTDIR=/work/system dedup"; install = "make " + jobsFlagE + " " + loadFlagE + " DESTDIR=/work/system dedup";
}; };
+1 -1
View File
@@ -18,7 +18,7 @@ package fontconfig {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
gettext, gettext,
gperf, gperf,
gzip, gzip,
+1 -1
View File
@@ -22,7 +22,7 @@ package fuse {
postCompile = "python3 -m pytest test/"; postCompile = "python3 -m pytest test/";
// this project uses pytest // this project uses pytest
skipTest = true; test = false;
}; };
inputs = [ 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 // 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 // well in its current state. That does not matter as long as the
// toolchain it produces passes its own test suite. // toolchain it produces passes its own test suite.
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
+1 -1
View File
@@ -23,7 +23,7 @@ rm -f /system/bin/httpd
bin = [ "perl" ]; bin = [ "perl" ];
populateUsrBin = true; populateUsrBin = true;
exec = make { exec = make {
inPlace = true; chdir = false;
generate = "make configure"; generate = "make configure";
preMake = ` preMake = `
+9 -9
View File
@@ -19,7 +19,7 @@ chmod +w tests/test-c32ispunct.sh && echo '#!/bin/sh' > tests/test-c32ispunct.sh
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
}; };
inputs = [ inputs = [
@@ -114,7 +114,7 @@ package libtool {
exec = make { exec = make {
// _Z2a2c: symbol not found // _Z2a2c: symbol not found
skipEarlyStageCheck = true; checkEarly = false;
check = [ check = [
"TESTSUITEFLAGS=" + jobsFlagE, "TESTSUITEFLAGS=" + jobsFlagE,
@@ -142,7 +142,7 @@ package gzip {
exec = make { exec = make {
// dependency loop // dependency loop
skipCheck = true; check = nil;
}; };
} }
@@ -197,7 +197,7 @@ test_disable '#!/bin/sh' tests/cmp
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
}; };
} }
@@ -223,7 +223,7 @@ test_disable '#!/bin/sh' tests/need-filename
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
}; };
} }
@@ -334,7 +334,7 @@ package bash {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
configure = { configure = {
"without-bash-malloc"; "without-bash-malloc";
}; };
@@ -371,7 +371,7 @@ test_disable 'int main(){return 0;}' gnulib-tests/test-lchown.c
`; `;
exec = make { exec = make {
omitDefaults = true; defaults = false;
configure = { configure = {
"enable-single-binary": "symlinks"; "enable-single-binary": "symlinks";
}; };
@@ -436,7 +436,7 @@ package texinfo {
exec = make { exec = make {
// nonstandard glibc extension // nonstandard glibc extension
skipCheck = true; check = nil;
}; };
inputs = [ perl ]; inputs = [ perl ];
@@ -648,7 +648,7 @@ package mpc {
enterSource = true; enterSource = true;
exec = make { exec = make {
inPlace = true; chdir = false;
generate = "autoreconf -vfi"; generate = "autoreconf -vfi";
}; };
+1 -1
View File
@@ -47,7 +47,7 @@ echo 'int main(){return 0;}' > tests/mini-dtls-fragments.c
bison, bison,
gettext, gettext,
gperf, gperf,
pkg-config, pkgconf,
python, python,
texinfo, 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"; website = "https://go.dev";
anitya = 1227; anitya = 1227;
version# = "1.26.5"; version# = "1.26.6";
source = remoteTar { source = remoteTar {
url = "https://go.dev/dl/go"+version+".src.tar.gz"; url = "https://go.dev/dl/go"+version+".src.tar.gz";
checksum = "13yt1u_NGOd62LO-WZ8W6CUXodOrEF5CdkiTTiH9E635IHn1luvlXYjsHpBXNFSw"; checksum = "BJQz9rGJ7ElMsZGURH7lw48Hw0x88RwdQJpINMomtgGCMK3AtwGCxDRkLE9REh5r";
compress = gzip; compress = gzip;
}; };
patches = [ patches = [
// https://go.dev/issue/77674 // https://go.dev/issue/77674
"746640.patch", "746640.patch",
// https://go.dev/issue/80308
"799064.patch",
]; ];
env = [ env = [
@@ -27,7 +25,7 @@ package go {
enterSource = true; enterSource = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
mkdir /work/system/ "${TMPDIR}" mkdir /work/system/ "${TMPDIR}"
cp -r . /work/system/go cp -r . /work/system/go
+2 -2
View File
@@ -3,12 +3,12 @@ package googletest {
exclude = true; exclude = true;
anitya = 18290; anitya = 18290;
version# = "1.17.0"; version# = "1.18.0";
output = remoteGitHubRelease { output = remoteGitHubRelease {
suffix = "google/googletest"; suffix = "google/googletest";
tag = "v"+version; tag = "v"+version;
name = "googletest-"+version+".tar.gz"; name = "googletest-"+version+".tar.gz";
checksum = "-1r3ch8vPP8COF7xUH5hyX6bEJ4dN9TQh4IxrmpHr6vaig6mA3DdUpV4cihQ_9dw"; checksum = "ABVPC5sduQR7xfkZQm7UHSmBTaAJcVPRHS_lNMhlL99HU_YffpFmXbwRKeG1ZY8A";
compress = gzip; compress = gzip;
}; };
} }
@@ -2,11 +2,11 @@ package hakurei-source {
description = "hakurei source tree"; description = "hakurei source tree";
exclude = true; exclude = true;
version# = "0.4.5"; version# = "0.4.6";
output = remoteTar { output = remoteTar {
url = "https://git.gensokyo.uk/rosa/hakurei/archive/"+ url = "https://git.gensokyo.uk/rosa/hakurei/archive/"+
"v"+version+".tar.gz"; "v"+version+".tar.gz";
checksum = "5bvbuIRcDIrtijogwqXn3y8h5f3rVS4ZSVhOig6Galfzt3g-O3Ufb-tHL1kQCQWK"; checksum = "2HxvdykuSSymAu-c1WIwQAy3qT4dDm8B--93iL4uomBlBC8wfSWldbvPF1noNkUC";
compress = gzip; compress = gzip;
}; };
} }
@@ -27,16 +27,9 @@ package hakurei {
"CC=clang -O3 -Werror", "CC=clang -O3 -Werror",
]; ];
files = {
"hostname/main.go": "hostname";
};
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
echo 'Building test helper (hostname).'
go build -o /bin/hostname /usr/src/hostname/main.go
mkdir -p /work/system/libexec/hakurei/ mkdir -p /work/system/libexec/hakurei/
echo "Building hakurei for $(go env GOOS)/$(go env GOARCH)." echo "Building hakurei for $(go env GOOS)/$(go env GOARCH)."
@@ -71,7 +64,8 @@ mkdir -p /work/system/bin/
inputs = [ inputs = [
go, go,
pkg-config, pkgconf,
net-tools,
libseccomp, libseccomp,
acl, acl,
@@ -98,16 +92,9 @@ package hakurei-dist {
"CC=clang -O3 -Werror", "CC=clang -O3 -Werror",
]; ];
files = {
"hostname/main.go": "hostname";
};
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
echo 'Building test helper (hostname).'
go build -o /bin/hostname /usr/src/hostname/main.go
NAME=make`; NAME=make`;
check = ` check = `
NAME=all`; NAME=all`;
@@ -118,7 +105,8 @@ DESTDIR=/work "./${NAME}.sh"
inputs = [ inputs = [
go, go,
pkg-config, pkgconf,
net-tools,
libseccomp, libseccomp,
acl, acl,
@@ -146,7 +134,7 @@ package earlyinit {
]; ];
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
echo '# Building earlyinit.' echo '# Building earlyinit.'
go build -trimpath -v -o /work/ -ldflags="-s -w 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"; website = "https://harfbuzz.github.io";
anitya = 1299; anitya = 1299;
version# = "14.3.0"; version# = "14.3.1";
source = remoteGitHub { source = remoteGitHub {
suffix = "harfbuzz/harfbuzz"; suffix = "harfbuzz/harfbuzz";
tag = version; tag = version;
checksum = "C03eSJbyFvrOPXWhlHgwxfqUKyR9xQO_FKzbwQzT7hW9DTUAQIiwvUIf_6cqaKPm"; checksum = "ykVwQNNbvY38Y27VjAfk16SGcEO5NY5A8CFxJCJ8z0ARh5MdLImmONpy-ZSb79Il";
}; };
exec = meson { exec = meson {
+2 -2
View File
@@ -15,9 +15,9 @@ package hwdata {
exec = make { exec = make {
// awk: fatal: cannot open file `hwdata.spec' for reading: No such file or directory // 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") // lspci: Unknown option 'A' (see "lspci --help")
skipCheck = true; check = nil;
}; };
} }
+3 -3
View File
@@ -21,7 +21,7 @@ package iproute2 {
chmod = true; chmod = true;
exec = make { exec = make {
inPlace = true; chdir = false;
// drop default autoconf options // drop default autoconf options
configureName = "./configure"; configureName = "./configure";
configure = { configure = {
@@ -30,11 +30,11 @@ package iproute2 {
}; };
make = [ "CC=cc", "YACC=yacc" ]; make = [ "CC=cc", "YACC=yacc" ];
// wants root // wants root
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
pkg-config, pkgconf,
m4, m4,
byacc, byacc,
flex, flex,
+1 -1
View File
@@ -1,6 +1,6 @@
# #
# Automatically generated file; DO NOT EDIT. # 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_CC_VERSION_TEXT="clang version 22.1.8"
CONFIG_GCC_VERSION=0 CONFIG_GCC_VERSION=0
+1 -1
View File
@@ -1,6 +1,6 @@
# #
# Automatically generated file; DO NOT EDIT. # 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_CC_VERSION_TEXT="clang version 22.1.8"
CONFIG_GCC_VERSION=0 CONFIG_GCC_VERSION=0
+13 -12
View File
@@ -3,11 +3,11 @@ package kernel-source {
website = "https://kernel.org"; website = "https://kernel.org";
exclude = true; exclude = true;
version# = "6.18.43"; version# = "6.18.44";
output = remoteTar { output = remoteTar {
url = "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+ url = "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/"+
"snapshot/linux-"+version+".tar.gz"; "snapshot/linux-"+version+".tar.gz";
checksum = "SthN8PgD7oze4syBC54KJoky7JUpAmXJO0Y98an1ZJiqGppnf6N3kmZiZZdvi9dd"; checksum = "yNPGMl3A-EgU6LgD37PAcXIa9iUtP-AmoJuQozfGRSq6Eg1Eq4fdbpKy3iWewU9_";
compress = gzip; compress = gzip;
}; };
} }
@@ -25,8 +25,8 @@ package kernel-headers {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipConfigure = true; configure = nil;
make = [ make = [
"-f /usr/src/kernel-headers/Makefile", "-f /usr/src/kernel-headers/Makefile",
"O=/tmp/kbuild", "O=/tmp/kbuild",
@@ -35,7 +35,7 @@ package kernel-headers {
"INSTALL_HDR_PATH=/work/system", "INSTALL_HDR_PATH=/work/system",
"headers_install", "headers_install",
]; ];
skipCheck = true; check = nil;
install = ` install = `
cat \ cat \
/usr/src/version.h > \ /usr/src/version.h > \
@@ -46,9 +46,9 @@ cat \
checksum = arch { checksum = arch {
default = ""; default = "";
amd64 = "mZZqI0tEpqbr3sQKOFLBeNv-DC7pkHNqPI7JdSSmo40sFCF2XnAMcah1DcUK2HTe"; amd64 = "vN5Ts9yAlHTntcQcNGJSisY5guYsYfvGnQqI1NzTBzvhBMPD432WB3B0KFGYQntA";
arm64 = "e6cD6TsBr1e-zONKtocvbRwmSnxqC_2K7A2KvMcO6lnpt4MXL1gsyx6k-BXqC19Z"; arm64 = "FQtpqCA0tlz17RJP8a5t9YEM_6F9kGPqQ9Z60gFrkVP3v8_P-Vnf5S7wLlxyRlOe";
riscv64 = "cljgtOrTCpyXoQLaKVmnnWPbCWkoXuMIVNjc6YXsy-zgsFzRA-H8yfJ1NojS867z"; riscv64 = "U5yQ9TI5_7diyrCcm2Iqh3XCMl0P60oQGeDMWxt3OQ91zFWPQ5FCH-eoYG9tSTMT";
}; };
inputs = [ rsync ]; inputs = [ rsync ];
} }
@@ -86,11 +86,12 @@ install -Dm0500 \
exclusive = true; exclusive = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipConfigure = true;
configure = nil;
// Build, install, and boot kernel before running kselftest on it. // Build, install, and boot kernel before running kselftest on it.
skipCheck = true; check = nil;
make = [ make = [
"-f /usr/src/kernel/Makefile", "-f /usr/src/kernel/Makefile",
@@ -154,7 +155,7 @@ package gen_init_cpio {
enterSource = true; enterSource = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
mkdir -p /work/system/bin/ mkdir -p /work/system/bin/
cc -o /work/system/bin/gen_init_cpio usr/gen_init_cpio.c 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. # 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_CC_VERSION_TEXT="clang version 22.1.8"
CONFIG_GCC_VERSION=0 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 KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
#define LINUX_VERSION_MAJOR 6 #define LINUX_VERSION_MAJOR 6
#define LINUX_VERSION_PATCHLEVEL 18 #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 // makes assumptions about the running kernel
skipTest = true; test = false;
}; };
inputs = [ inputs = [
+2 -2
View File
@@ -18,8 +18,8 @@ package libaio {
env = [ "PATH=/system/sbin" ]; env = [ "PATH=/system/sbin" ];
bin = [ "bash" ]; bin = [ "bash" ];
exec = make { exec = make {
inPlace = true; chdir = false;
skipConfigure = true; configure = nil;
preCheck = "rm harness/cases/20.t; "+ // flaky preCheck = "rm harness/cases/20.t; "+ // flaky
"CFLAGS='"+ "CFLAGS='"+
"-Wno-unknown-warning-option "+ "-Wno-unknown-warning-option "+
+3 -3
View File
@@ -16,9 +16,9 @@ package libbpf {
chmod = true; chmod = true;
exec = make { exec = make {
inPlace = true; chdir = false;
skipConfigure = true; configure = nil;
skipCheck = true; check = nil;
install = "make DESTDIR=/work LIBSUBDIR=lib install"; install = "make DESTDIR=/work LIBSUBDIR=lib install";
}; };
+4 -12
View File
@@ -23,18 +23,10 @@ package libcap {
bin = [ "bash" ]; bin = [ "bash" ];
exec = make { exec = make {
skipConfigure = true; chdir = false;
inPlace = true; configure = nil;
make = [ "CC=cc", "all" ];
make = [ check = [ "CC=cc", "test" ];
"CC=cc",
"all",
];
check = [
"CC=cc",
"test",
];
}; };
inputs = [ inputs = [
+2 -2
View File
@@ -3,7 +3,7 @@ package libexpat {
website = "https://libexpat.github.io"; website = "https://libexpat.github.io";
anitya = 770; anitya = 770;
version# = "2.8.2"; version# = "2.8.3";
source = remoteGitHubRelease { source = remoteGitHubRelease {
suffix = "libexpat/libexpat"; suffix = "libexpat/libexpat";
tag = "R_"+replace { tag = "R_"+replace {
@@ -12,7 +12,7 @@ package libexpat {
new = "_"; new = "_";
}; };
name = "expat-"+version+".tar.bz2"; name = "expat-"+version+".tar.bz2";
checksum = "98Pdyj5QtO7QRtNFXTWsCNCixQDx701ZGql2B-JIrTDkw49J5WXXUwnS4AdMlM4L"; checksum = "prHQc14YY3Gp6BfflneNcVyRXM-AxFCqiigxrGL9TT1sGhVODvI_9JNR2xnZlZSj";
compress = bzip2; compress = bzip2;
}; };
+3 -3
View File
@@ -3,12 +3,12 @@ package libpsl {
website = "https://rockdaboot.github.io/libpsl"; website = "https://rockdaboot.github.io/libpsl";
anitya = 7305; anitya = 7305;
version# = "0.23.1"; version# = "0.23.2";
source = remoteGitHubRelease { source = remoteGitHubRelease {
suffix = "rockdaboot/libpsl"; suffix = "rockdaboot/libpsl";
tag = version; tag = version;
name = "libpsl-"+version+".tar.gz"; name = "libpsl-"+version+".tar.gz";
checksum = "9wu0JxiNGfY3TuYeCmOq9Xm3faPHole5is_3ZL2KUCh8FyaYwpl7a85SNsz8FmPz"; checksum = "-XIKaQK0QoyzXpwezyvGzDdIBCUTqPyd8jU6axIusrnma-qsYxhLUO1Oycwcelr2";
compress = gzip; compress = gzip;
}; };
@@ -22,7 +22,7 @@ test_disable 'int main(){return 0;}' tests/test-is-public-builtin.c
exec = make {}; exec = make {};
inputs = [ inputs = [
pkg-config, pkgconf,
python, python,
]; ];
} }
+2 -2
View File
@@ -20,7 +20,7 @@ package libtirpc {
exec = make { exec = make {
generate = "sh -e ./bootstrap"; generate = "sh -e ./bootstrap";
configure = { configure = {
"CFLAGS": `"$(pkg-config --cflags libbsd-overlay) ${CFLAGS:-}"`; "CFLAGS": `"$(pkgconf --cflags libbsd-overlay) ${CFLAGS:-}"`;
"disable-gssapi"; "disable-gssapi";
}; };
}; };
@@ -28,7 +28,7 @@ package libtirpc {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
libbsd, libbsd,
kernel-headers, kernel-headers,
+4 -6
View File
@@ -16,13 +16,11 @@ package libucontext {
enterSource = true; enterSource = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipConfigure = true; chdir = false;
inPlace = true;
make = [ configure = nil;
"ARCH=" + linuxArch, make = [ "ARCH=" + linuxArch ];
];
install = "make prefix=/system DESTDIR=/work install"; install = "make prefix=/system DESTDIR=/work install";
}; };
} }
+2 -2
View File
@@ -15,14 +15,14 @@ package libxslt {
generate = "NOCONFIGURE=1 ./autogen.sh"; generate = "NOCONFIGURE=1 ./autogen.sh";
// python libxml2 cyclic dependency // python libxml2 cyclic dependency
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
automake, automake,
libtool, libtool,
python, python,
pkg-config, pkgconf,
libxml2, libxml2,
]; ];
+1 -1
View File
@@ -7,7 +7,7 @@ package lit {
exec = pip { exec = pip {
append = [ "llvm", "utils", "lit" ]; append = [ "llvm", "utils", "lit" ];
// already checked during llvm // already checked during llvm
skipCheck = true; check = nil;
}; };
inputs = [ python-setuptools ]; inputs = [ python-setuptools ];
+2 -2
View File
@@ -56,7 +56,7 @@ message(NOTICE "${LLVM_VERSION_MAJOR}")
"COMPILER_RT_BUILD_PROFILE": "OFF"; "COMPILER_RT_BUILD_PROFILE": "OFF";
"COMPILER_RT_BUILD_XRAY": "OFF"; "COMPILER_RT_BUILD_XRAY": "OFF";
}; };
skipTest = true; test = nil;
postInstall = ` postInstall = `
mkdir -p "/work/system/lib/clang/$LLVM_VERSION_MAJOR/lib/" mkdir -p "/work/system/lib/clang/$LLVM_VERSION_MAJOR/lib/"
ln -s \ ln -s \
@@ -119,7 +119,7 @@ package early-runtimes {
"LLVM_ENABLE_ZSTD": "FORCE_ON"; "LLVM_ENABLE_ZSTD": "FORCE_ON";
"LLVM_ENABLE_LIBXML2": "OFF"; "LLVM_ENABLE_LIBXML2": "OFF";
}; };
skipTest = true; test = nil;
}; };
inputs = [ inputs = [
+4 -14
View File
@@ -17,20 +17,10 @@ package lm_sensors {
bin = [ "perl" ]; bin = [ "perl" ];
populateUsrBin = true; populateUsrBin = true;
exec = make { exec = make {
inPlace = true; chdir = false;
skipConfigure = true; configure = nil;
make = [ "CC=cc", "ETCDIR=/system/etc", "PREFIX=/system" ];
make = [ check = [ "CC=cc", "check" ];
"CC=cc",
"ETCDIR=/system/etc",
"PREFIX=/system",
];
check = [
"CC=cc",
"check",
];
install = "make DESTDIR=/work PREFIX=/system install"; install = "make DESTDIR=/work PREFIX=/system install";
}; };
+2 -2
View File
@@ -20,8 +20,8 @@ package lua {
chmod = true; chmod = true;
exec = make { exec = make {
inPlace = true; chdir = false;
skipConfigure = true; configure = nil;
make = [ "CC='clang -fPIC'", "all" ]; make = [ "CC='clang -fPIC'", "all" ];
check = [ "test" ]; check = [ "test" ];
install = ` install = `
+2 -2
View File
@@ -16,11 +16,11 @@ package lvm2 {
exec = make { exec = make {
// requires root // requires root
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
pkg-config, pkgconf,
libaio, libaio,
kernel-headers, kernel-headers,
+2 -2
View File
@@ -3,11 +3,11 @@ package meson {
website = "https://mesonbuild.com"; website = "https://mesonbuild.com";
anitya = 6472; anitya = 6472;
version# = "1.11.2"; version# = "1.12.0";
source = remoteGitHub { source = remoteGitHub {
suffix = "mesonbuild/meson"; suffix = "mesonbuild/meson";
tag = version; tag = version;
checksum = "9AMilGxTOVqPA2DaGMASyuVs1BeTzgDZ0NH2oSYoRZk846ApvfOBa4cc18XEEK7M"; checksum = "K0hm0h26_6e3-1poYZKwj18IB6bdAtYE-whpROtTCSpVN5GllwSwbXC2xPYcSFAJ";
}; };
patches = [ patches = [
"respect-colour.patch", "respect-colour.patch",
+1 -1
View File
@@ -21,6 +21,6 @@ package musl-fts {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
]; ];
} }
+1 -1
View File
@@ -21,6 +21,6 @@ package musl-obstack {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
]; ];
} }
+5 -11
View File
@@ -23,14 +23,9 @@ package musl-headers {
]; ];
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipCheck = true; make = [ "DESTDIR=/work", "install-headers" ];
check = nil;
make = [
"DESTDIR=/work",
"install-headers",
];
install = "# headers installed during make"; install = "# headers installed during make";
}; };
@@ -53,9 +48,8 @@ package musl {
]; ];
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipCheck = true; check = nil;
postInstall = ` postInstall = `
mkdir -p /work/system/bin mkdir -p /work/system/bin
COMPAT_LINKER_NAME="ld-musl-` + linuxArch + `.so.1" 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. // "tests" are actual demo programs, not a test suite.
skipCheck = true; check = nil;
postInstall = ` postInstall = `
find /work/system/lib \ 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 = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
libmnl, libmnl,
kernel-headers, kernel-headers,
@@ -95,7 +95,7 @@ chmod +w /etc/ && ln -s ../usr/src/iptables/etc/ethertypes /etc/
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
bash, bash,
python, python,
+1 -1
View File
@@ -12,7 +12,7 @@ package noto {
enterSource = true; enterSource = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
install = ` install = `
DEST=/work/system/share/fonts/noto DEST=/work/system/share/fonts/noto
for font in $(ls -d fonts/*/); do 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"; website = "https://firefox-source-docs.mozilla.org/security/nss/index.html";
anitya = 2503; anitya = 2503;
version# = "3.126"; version# = "3.126.1";
source = remoteGitHub { source = remoteGitHub {
suffix = "nss-dev/nss"; suffix = "nss-dev/nss";
tag = "NSS_"+join { tag = "NSS_"+join {
@@ -28,7 +28,7 @@ package nss {
}; };
sep = "_"; sep = "_";
}+"_RTM"; }+"_RTM";
checksum = "gzMK4RkCHhgmhe33imV0qzZ8e2_VFAsF5M2db-1jrCWzh6XGijm51P2DIdDO2Dsf"; checksum = "3J7o7P3KlE8Cen4fzHLwvDKA1rrcJ84yBTniJHcIBw59LPT-7Q0NxL2CC4BKGW3F";
}; };
extra = [ nspr ]; extra = [ nspr ];
@@ -38,10 +38,9 @@ package nss {
early = "\nln -s extra/nspr/nspr /usr/src/nspr\nchmod +w ../nspr/\n"; early = "\nln -s extra/nspr/nspr /usr/src/nspr\nchmod +w ../nspr/\n";
exec = make { exec = make {
omitDefaults = true; defaults = false;
skipConfigure = true; chdir = false;
inPlace = true; configure = nil;
make = [ make = [
"CCC=clang++", "CCC=clang++",
"NSDISTMODE=copy", "NSDISTMODE=copy",
@@ -49,7 +48,7 @@ package nss {
"USE_64=1", "USE_64=1",
"nss_build_all", "nss_build_all",
]; ];
skipCheck = true; check = nil;
install = ` install = `
cp -r \ cp -r \
/usr/src/dist/. \ /usr/src/dist/. \
@@ -80,7 +79,7 @@ package nss-cacert {
enterSource = true; enterSource = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
mkdir -p /work/system/etc/ssl/{certs/unbundled,certs/hashed,trust-source} mkdir -p /work/system/etc/ssl/{certs/unbundled,certs/hashed,trust-source}
buildcatrust \ buildcatrust \
+3 -5
View File
@@ -5,14 +5,12 @@ package openssl {
// strange malformed tags treated as pre-releases in Anitya // strange malformed tags treated as pre-releases in Anitya
latest = anityaFallback; latest = anityaFallback;
block = "python"; version# = "4.0.1";
version# = "3.6.2";
source = remoteGitHubRelease { source = remoteGitHubRelease {
suffix = "openssl/openssl"; suffix = "openssl/openssl";
tag = "openssl-"+version; tag = "openssl-"+version;
name = "openssl-"+version+".tar.gz"; name = "openssl-"+version+".tar.gz";
checksum = "jH004dXTiE01Hp0kyShkWXwrSHEksZi4i_3v47D9H9Uz9LQ1aMwF7mrl2Tb4t_XA"; checksum = "8FLTB0bZAKyjpmgO4kU5Og-XuSb2_77fxDfEbpOMPKTnIWxQDo7n8e4UdUuc2YIc";
compress = gzip; compress = gzip;
}; };
@@ -21,7 +19,7 @@ package openssl {
]; ];
exec = make { exec = make {
omitDefaults = true; defaults = false;
configureName = "/usr/src/openssl/Configure"; configureName = "/usr/src/openssl/Configure";
configure = { configure = {
+1 -1
View File
@@ -18,7 +18,7 @@ package pango {
"cairo": "enabled"; "cairo": "enabled";
}; };
// Fontconfig error: Cannot load default config file: File not found: /etc/fonts/fonts.conf // Fontconfig error: Cannot load default config file: File not found: /etc/fonts/fonts.conf
skipTest = true; test = false;
}; };
inputs = [ inputs = [
+3 -3
View File
@@ -28,8 +28,8 @@ disable_test ext/POSIX/t/time.t
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
inPlace = true; chdir = false;
configureName = "./Configure"; configureName = "./Configure";
configure = { configure = {
@@ -70,7 +70,7 @@ package perl-Module-Build {
chmod = true; chmod = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
perl Build.PL --prefix=/system perl Build.PL --prefix=/system
./Build build`; ./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"; website = "https://gitlab.com/procps-ng/procps";
anitya = 3708; anitya = 3708;
version# = "4.0.6"; version# = "4.0.7";
source = remoteGitLab { source = remoteGitLab {
domain = "gitlab.com"; domain = "gitlab.com";
suffix = "procps-ng/procps"; suffix = "procps-ng/procps";
ref = "v"+version; ref = "v"+version;
checksum = "pl_fZLvDlv6iZTkm8l_tHFpzTDVFGCiSJEs3eu0zAX6u36AV36P_En8K7JPScRWM"; checksum = "h5d0Wd_YyDzeRyduE4YawF0edvyMWA3UBcAXWAMg2fdtHhl5i1r0QeDu1-xAyR8g";
}; };
exec = make { exec = make {
@@ -24,6 +24,6 @@ package procps {
libtool, libtool,
gzip, gzip,
pkg-config, pkgconf,
]; ];
} }
+65 -21
View File
@@ -3,11 +3,14 @@ package python {
website = "https://www.python.org"; website = "https://www.python.org";
anitya = 13254; anitya = 13254;
version# = "3.14.7"; // too many inputs; early variant available
bootstrap = false;
version# = "3.15.0";
source = remoteTar { source = remoteTar {
url = "https://www.python.org/ftp/python/"+version+ url = "https://www.python.org/ftp/python/"+version+
"/Python-"+version+".tgz"; "/Python-"+version+"rc1.tgz";
checksum = "hXLV7_BGEFZvQ04DNIlk5IdoRZd9DkQt4abKhc8rWsLXHTeSboAWTewJ6l0-LxVz"; checksum = "llRZNKCqDOxnAiLU-2bSneXZcssNtdzG9bBgfyfiGchLSbT7gNvls4ekdmMklgKl";
compress = gzip; compress = gzip;
}; };
patches = [ "zipfile-no-default-strict_timestamps.patch" ]; patches = [ "zipfile-no-default-strict_timestamps.patch" ];
@@ -148,18 +151,18 @@ package python-setuptools {
website = "https://pypi.org/project/setuptools"; website = "https://pypi.org/project/setuptools";
anitya = 4021; anitya = 4021;
version# = "83.0.0"; version# = "84.0.0";
source = remoteGitHub { source = remoteGitHub {
suffix = "pypa/setuptools"; suffix = "pypa/setuptools";
tag = "v"+version; tag = "v"+version;
checksum = "WqYSqCAvwpcIG6yXV8vVzRMNWl2CrcPOUPwlYrLV70ykHSpKxW1-XYQ4Z4n0ebAt"; checksum = "K9PGFv7ju_v4sykQCcROCc8Zdz3TfxYv95JlKFGXUnpf1yqRZW3oA0LuUQfE2x8n";
}; };
exec = pip { exec = pip {
// error: invalid command 'dist_info' // error: invalid command 'dist_info'
buildIsolation = true; buildIsolation = true;
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
runtime = [ python ]; runtime = [ python ];
@@ -170,12 +173,13 @@ package python-wheel {
website = "https://peps.python.org/pep-0427"; website = "https://peps.python.org/pep-0427";
anitya = 11428; anitya = 11428;
version# = "0.47.0"; version# = "0.48.0";
source = remoteGitHub { source = remoteGitHub {
suffix = "pypa/wheel"; suffix = "pypa/wheel";
tag = version; tag = version;
checksum = "HZ-MvkUP8mbbx2YmsRNswj_bbOCIiXckuHqL5Qbvb5NxN5DYfWnqwkGNyS7OrId0"; checksum = "h-UZQHS-NwB3b9YxYpJePR5cbDGZaKxz4bdhYjilWdQXAE46SV7A1CwZKzZcuZFh";
}; };
patches = [ "wheel-test-colour.patch" ];
exec = pip { exec = pip {
install = true; install = true;
@@ -209,7 +213,7 @@ package python-vcs-versioning {
// upstream is monorepo of two packages (setuptools-scm) // upstream is monorepo of two packages (setuptools-scm)
append = [ "vcs-versioning" ]; append = [ "vcs-versioning" ];
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
@@ -243,7 +247,7 @@ package python-setuptools-scm {
// upstream is monorepo of two packages // upstream is monorepo of two packages
append = [ "setuptools-scm" ]; append = [ "setuptools-scm" ];
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
@@ -273,7 +277,7 @@ package python-flit-core {
// upstream has other unused packages with many dependencies // upstream has other unused packages with many dependencies
append = [ "flit_core" ]; append = [ "flit_core" ];
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
runtime = [ python ]; runtime = [ python ];
@@ -293,7 +297,7 @@ package python-packaging {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-flit-core ]; inputs = [ python-flit-core ];
@@ -314,7 +318,7 @@ package python-pathspec {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-flit-core ]; inputs = [ python-flit-core ];
@@ -335,7 +339,7 @@ package python-trove-classifiers {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-setuptools ]; inputs = [ python-setuptools ];
@@ -360,30 +364,68 @@ package python-pluggy {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-setuptools-scm ]; inputs = [ python-setuptools-scm ];
runtime = [ python ]; 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 { package python-hatchling {
description = "the extensible, standards compliant build backend used by Hatch"; description = "the extensible, standards compliant build backend used by Hatch";
website = "https://hatch.pypa.io"; website = "https://hatch.pypa.io";
anitya = 16137; anitya = 16137;
version# = "1.17.1"; version# = "1.18.0";
source = remoteGitHub { source = remoteGitHub {
suffix = "pypa/hatch"; suffix = "pypa/hatch";
tag = "hatch-v"+version; tag = "hatch-v"+version;
checksum = "FK9PkGIkL3wyVFHOKrx9lSRqoevuQ_TFrN-pMqsoFKsh5eim4pfzx7MvL3ioif9o"; checksum = "a_ntndxBlMdqSVW3PkiAY42m-NDgyWJcKLWFIVTB_5PciVeJdYYdbcdF6jsd0U96";
}; };
exec = pip { exec = pip {
// upstream has other unused packages with many dependencies // upstream has other unused packages with many dependencies
append = [ "backend" ]; append = [ "backend" ];
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
@@ -391,6 +433,7 @@ package python-hatchling {
python-pathspec, python-pathspec,
python-trove-classifiers, python-trove-classifiers,
python-pluggy, python-pluggy,
python-tomlkit,
]; ];
runtime = [ runtime = [
@@ -398,6 +441,7 @@ package python-hatchling {
python-pathspec, python-pathspec,
python-trove-classifiers, python-trove-classifiers,
python-pluggy, python-pluggy,
python-tomlkit,
]; ];
} }
@@ -415,7 +459,7 @@ package python-pygments {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-hatchling ]; inputs = [ python-hatchling ];
@@ -440,7 +484,7 @@ package python-iniconfig {
exec = pip { exec = pip {
// pytest circular dependency // pytest circular dependency
skipCheck = true; check = nil;
}; };
inputs = [ python-setuptools-scm ]; inputs = [ python-setuptools-scm ];
@@ -465,7 +509,7 @@ package python-pytest {
exec = pip { exec = pip {
// many dependencies // many dependencies
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
@@ -0,0 +1,21 @@
diff --git a/tests/commands/util.py b/tests/commands/util.py
index 5d139d9..d18d103 100644
--- a/tests/commands/util.py
+++ b/tests/commands/util.py
@@ -2,7 +2,7 @@ from __future__ import annotations
import sys
from io import StringIO
-from os import PathLike
+from os import PathLike, environ
from subprocess import CalledProcessError
from unittest.mock import patch
@@ -10,6 +10,7 @@ import pytest
from wheel._commands import main
+environ["NO_COLOR"] = "1"
def run_command(
command: str, *args: str | PathLike, catch_systemexit: bool = True
@@ -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"; website = "https://www.qemu.org";
anitya = 13607; anitya = 13607;
version# = "11.0.3"; version# = "11.1.0";
source = remoteTar { source = remoteTar {
url = "https://download.qemu.org/qemu-"+version+".tar.bz2"; url = "https://download.qemu.org/qemu-"+version+".tar.bz2";
checksum = "cY1nZe92-WGeOErkkEXU0pDidJxBFgF4JCtUv1IJk0qVUYHw3VSZfVms1NqWfTLq"; checksum = "nOjPiAFhPGVBnM2rYokJhMDUhFM_6ec-B2N-1-LB1wmCiLzF5_ppqSgkNESuoBFu";
compress = bzip2; compress = bzip2;
}; };
patches = [ patches = [
"meson-colour.patch",
"iotests-zfs.patch",
"disable-mcast-test.patch", "disable-mcast-test.patch",
// fails with ipv6 disabled // fails with ipv6 disabled
"disable-netdev-socket.patch", "disable-netdev-socket.patch",
// fails on a slower machine
"copy-before-write-spurious.patch",
]; ];
// configure script uses source as scratch space // 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/[0-9][0-9][0-9]* \
tests/qemu-iotests/tests/copy-before-write \ tests/qemu-iotests/tests/copy-before-write \
tests/qemu-iotests/tests/file-io-error.out 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 { exec = make {
@@ -56,16 +58,17 @@ EOF
check = [ check = [
"TIMEOUT_MULTIPLIER=5", "TIMEOUT_MULTIPLIER=5",
"check",
]; ];
}; };
inputs = [ inputs = [
bash, bash,
python,
python-setuptools, python-setuptools,
python-wheel, python-wheel,
meson,
ninja, ninja,
pkg-config, pkgconf,
diffutils, diffutils,
openssl, openssl,
+3 -2
View File
@@ -15,7 +15,8 @@ package rsync {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
configure = { configure = {
"disable-openssl"; "disable-openssl";
"disable-xxhash"; "disable-xxhash";
@@ -24,6 +25,6 @@ package rsync {
}; };
// circular dependency // circular dependency
skipCheck = true; check = nil;
}; };
} }
+1 -1
View File
@@ -14,7 +14,7 @@ package spirv-headers {
exec = cmake { exec = cmake {
// upstream has no tests // upstream has no tests
skipTest = true; test = nil;
}; };
} }
+3 -4
View File
@@ -28,10 +28,9 @@ package squashfs-tools {
early = "cd squashfs-tools"; early = "cd squashfs-tools";
exec = make { exec = make {
skipConfigure = true; chdir = false;
inPlace = true; configure = nil;
check = nil;
skipCheck = true;
install = "make INSTALL_PREFIX=/work/system install"; install = "make INSTALL_PREFIX=/work/system install";
}; };
+1 -1
View File
@@ -19,7 +19,7 @@ package tamago {
enterSource = true; enterSource = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = ` build = `
mkdir /work/system/ mkdir /work/system/
cp -r . /work/system/tamago cp -r . /work/system/tamago
+8 -8
View File
@@ -22,10 +22,10 @@ package toybox {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
inPlace = true; chdir = false;
skipConfigure = true;
configure = nil;
preMake = ` preMake = `
LDFLAGS="${LDFLAGS:-''} -static" LDFLAGS="${LDFLAGS:-''} -static"
@@ -50,7 +50,7 @@ sed -i \
"USER=cure", "USER=cure",
"tests", "tests",
]; ];
skipEarlyStageCheck = true; checkEarly = false;
install = "PREFIX=/work/system/bin make install_flat"; install = "PREFIX=/work/system/bin make install_flat";
@@ -80,10 +80,10 @@ package toybox-early {
toyboxEarly = true; toyboxEarly = true;
exec = make { exec = make {
omitDefaults = true; defaults = false;
inPlace = true; chdir = false;
skipConfigure = true;
configure = nil;
preMake = ` preMake = `
LDFLAGS="${LDFLAGS:-''} -static" LDFLAGS="${LDFLAGS:-''} -static"
@@ -115,7 +115,7 @@ CONFIG_DIFF=y
"USER=cure", "USER=cure",
"tests", "tests",
]; ];
skipEarlyStageCheck = true; checkEarly = false;
install = "PREFIX=/work/system/bin make install_flat"; install = "PREFIX=/work/system/bin make install_flat";
+1 -1
View File
@@ -20,7 +20,7 @@ package unzip {
chmod = true; chmod = true;
exec = generic { exec = generic {
inPlace = true; chdir = false;
build = `unix/configure build = `unix/configure
make -f unix/Makefile generic1`; make -f unix/Makefile generic1`;
install = ` install = `
+1 -1
View File
@@ -47,7 +47,7 @@ package util-linux {
// check script claims: // check script claims:
// For development purpose only. // For development purpose only.
// Don't execute on production system! // Don't execute on production system!
skipCheck = true; check = nil;
}; };
inputs = [ inputs = [
+2 -2
View File
@@ -17,14 +17,14 @@ package vim {
enterSource = true; enterSource = true;
exec = make { exec = make {
inPlace = true; chdir = false;
configure = { configure = {
"with-tlib": "ncursesw"; "with-tlib": "ncursesw";
}; };
check = [ "test" ]; check = [ "test" ];
// very expensive // very expensive
skipCheck = true; check = nil;
}; };
inputs = [ ncurses ]; inputs = [ ncurses ];
+20 -20
View File
@@ -34,7 +34,7 @@ package libxtrans {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
]; ];
@@ -59,7 +59,7 @@ package xorgproto {
inputs = [ inputs = [
automake, automake,
pkg-config, pkgconf,
util-macros, util-macros,
]; ];
@@ -121,7 +121,7 @@ package xcb {
inputs = [ inputs = [
python, python,
pkg-config, pkgconf,
xcb-proto, xcb-proto,
libXau, libXau,
@@ -148,7 +148,7 @@ package libxcb-keysyms {
exec = make {}; exec = make {};
inputs = [ inputs = [
pkg-config, pkgconf,
xcb, xcb,
]; ];
@@ -172,7 +172,7 @@ package libxcb-wm {
inputs = [ inputs = [
m4, m4,
pkg-config, pkgconf,
xcb, xcb,
]; ];
@@ -196,7 +196,7 @@ package libxcb-util {
exec = make {}; exec = make {};
inputs = [ inputs = [
pkg-config, pkgconf,
util-macros, util-macros,
xcb, xcb,
@@ -220,7 +220,7 @@ package libxcb-image {
exec = make {}; exec = make {};
inputs = [ inputs = [
pkg-config, pkgconf,
libxcb-util, libxcb-util,
]; ];
@@ -244,7 +244,7 @@ package libxcb-render-util {
exec = make {}; exec = make {};
inputs = [ inputs = [
pkg-config, pkgconf,
util-macros, util-macros,
xcb, xcb,
@@ -278,7 +278,7 @@ package libX11 {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
libxtrans, libxtrans,
@@ -309,7 +309,7 @@ package libXext {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
libX11, libX11,
@@ -338,7 +338,7 @@ package libXfixes {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
xorgproto, xorgproto,
@@ -368,7 +368,7 @@ package libXrender {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
libX11, libX11,
@@ -397,7 +397,7 @@ package libxshmfence {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
xorgproto, xorgproto,
@@ -424,7 +424,7 @@ package libXxf86vm {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
libXext, libXext,
@@ -454,7 +454,7 @@ package libXrandr {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
libXext, libXext,
@@ -488,7 +488,7 @@ package font-util {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
]; ];
@@ -514,7 +514,7 @@ package libfontenc {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
font-util, font-util,
@@ -561,7 +561,7 @@ package xkbcomp {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
byacc, byacc,
util-macros, util-macros,
@@ -591,7 +591,7 @@ package libXfont2 {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
freetype, freetype,
@@ -642,7 +642,7 @@ package libXdmcp {
inputs = [ inputs = [
automake, automake,
libtool, libtool,
pkg-config, pkgconf,
util-macros, util-macros,
xorgproto, xorgproto,
+14
View File
@@ -320,6 +320,8 @@ type PackageAttr struct {
// Whether to replace /usr/bin/ with a symlink to /bin/. // Whether to replace /usr/bin/ with a symlink to /bin/.
PopulateUsrBin bool PopulateUsrBin bool
// Whether this package is disallowed from bootstrap stages.
Std bool
// Hint for an early variant of toybox to be used when available. // Hint for an early variant of toybox to be used when available.
Early bool Early bool
// Whether to omit output colour environment variables. // Whether to omit output colour environment variables.
@@ -375,6 +377,14 @@ func (t Toolchain) Append(a []pkg.Artifact, handles ...ArtifactH) []pkg.Artifact
return a 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. // New constructs a [pkg.Artifact] via a build system helper.
func (t Toolchain) New( func (t Toolchain) New(
name, version string, name, version string,
@@ -387,6 +397,10 @@ func (t Toolchain) New(
attr = new(PackageAttr) attr = new(PackageAttr)
} }
if attr.Std && !t.stage.isStd() {
panic(BootstrapError(name))
}
if name == "" || version == "" { if name == "" || version == "" {
panic("name must be non-empty") panic("name must be non-empty")
} }
+46 -12
View File
@@ -811,14 +811,17 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr GenericHelper var attr GenericHelper
chdir := true
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("inPlace"): &attr.InPlace, k("chdir"): &chdir,
k("build"): &attr.Build, k("build"): &attr.Build,
k("check"): &attr.Check, k("check"): &attr.Check,
k("install"): &attr.Install, k("install"): &attr.Install,
}); err != nil { }); err != nil {
return return
} }
attr.InPlace = !chdir
v = &attr v = &attr
set = true set = true
return return
@@ -828,28 +831,33 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr MakeHelper 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{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("omitDefaults"): &attr.OmitDefaults, k("defaults"): &defaults,
k("generate"): &attr.Generate, k("generate"): &attr.Generate,
k("preMake"): &attr.ScriptMakeEarly, k("preMake"): &attr.ScriptMakeEarly,
k("preCheck"): &attr.ScriptCheckEarly, k("preCheck"): &attr.ScriptCheckEarly,
k("postInstall"): &attr.Script, k("postInstall"): &attr.Script,
k("inPlace"): &attr.InPlace, k("chdir"): &chdir,
k("skipConfigure"): &attr.SkipConfigure,
k("configureName"): &attr.ConfigureName, k("configureName"): &attr.ConfigureName,
k("forceAutoconf"): &attr.ForceAutoconf, k("forceAutoconf"): &attr.ForceAutoconf,
k("configure"): &attr.Configure, k("configure"): &attr.Configure,
k("host"): &attr.Host, k("host"): &attr.Host,
k("build"): &attr.Build, k("build"): &attr.Build,
k("make"): &attr.Make, k("make"): &attr.Make,
k("skipCheck"): &attr.SkipCheck,
k("check"): &attr.Check, k("check"): &attr.Check,
k("install"): &attr.Install, k("install"): &attr.Install,
k("skipEarlyStageCheck"): &attr.SkipCheckEarly, k("checkEarly"): &checkEarly,
}); err != nil { }); err != nil {
return return
} }
attr.OmitDefaults, attr.InPlace = !defaults, !chdir
attr.SkipConfigure = attr.Configure == nil
attr.SkipCheck = attr.Check == nil
attr.SkipCheckEarly = !checkEarly
v = &attr v = &attr
set = true set = true
return return
@@ -859,17 +867,20 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr CMakeHelper var attr CMakeHelper
var test azalea.AString
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("append"): &attr.Append, k("append"): &attr.Append,
k("buildType"): &attr.BuildType, k("buildType"): &attr.BuildType,
k("cache"): &attr.Cache, k("cache"): &attr.Cache,
k("postInstall"): &attr.Script, k("postInstall"): &attr.Script,
k("test"): &attr.Test, k("test"): &test,
k("skipTest"): &attr.SkipTest,
k("make"): &attr.Make, k("make"): &attr.Make,
}); err != nil { }); err != nil {
return return
} }
attr.Test = test.V
attr.SkipTest = test.Nil
v = &attr v = &attr
set = true set = true
return return
@@ -879,18 +890,21 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr MesonHelper var attr MesonHelper
test := true
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("muon"): &attr.Muon, k("muon"): &attr.Muon,
k("preCompile"): &attr.ScriptCompileEarly, k("preCompile"): &attr.ScriptCompileEarly,
k("postCompile"): &attr.ScriptCompiled, k("postCompile"): &attr.ScriptCompiled,
k("postInstall"): &attr.Script, k("postInstall"): &attr.Script,
k("setup"): &attr.Setup, k("setup"): &attr.Setup,
k("skipTest"): &attr.SkipTest, k("test"): &test,
k("skipTests"): &attr.SkipTests, k("skipTests"): &attr.SkipTests,
k("interactiveTest"): &attr.InteractiveTest, k("interactiveTest"): &attr.InteractiveTest,
}); err != nil { }); err != nil {
return return
} }
attr.SkipTest = !test
v = &attr v = &attr
set = true set = true
return return
@@ -900,11 +914,13 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr MakeMakerHelper var attr MakeMakerHelper
doCheck := true
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("skipCheck"): &attr.SkipCheck, k("check"): &doCheck,
}); err != nil { }); err != nil {
return return
} }
attr.SkipCheck = !doCheck
v = &attr v = &attr
set = true set = true
return return
@@ -914,17 +930,20 @@ func (s *S) getFrame() azalea.Frame {
args azalea.FArgs, args azalea.FArgs,
) (v any, set bool, err error) { ) (v any, set bool, err error) {
var attr PipHelper var attr PipHelper
var scriptCheck azalea.AString
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("append"): &attr.Append, k("append"): &attr.Append,
k("buildIsolation"): &attr.BuildIsolation, k("buildIsolation"): &attr.BuildIsolation,
k("enterSource"): &attr.EnterSource, k("enterSource"): &attr.EnterSource,
k("install"): &attr.Install, k("install"): &attr.Install,
k("skipCheck"): &attr.SkipCheck, k("check"): &scriptCheck,
k("check"): &attr.Check,
k("postInstall"): &attr.Script, k("postInstall"): &attr.Script,
}); err != nil { }); err != nil {
return return
} }
attr.Check = scriptCheck.V
attr.SkipCheck = scriptCheck.Nil
v = &attr v = &attr
set = true set = true
return return
@@ -975,6 +994,13 @@ type evalContext struct {
t Toolchain 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]. // pf implements [azalea.PF].
func (ctx *evalContext) pf( func (ctx *evalContext) pf(
name azalea.Ident, name azalea.Ident,
@@ -998,6 +1024,8 @@ func (ctx *evalContext) pf(
overlay string overlay string
inputs, runtimes, extra azalea.Array inputs, runtimes, extra azalea.Array
bootstrap = true
) )
if err = args.Apply(map[unique.Handle[azalea.Ident]]any{ if err = args.Apply(map[unique.Handle[azalea.Ident]]any{
k("description"): &meta.Description, k("description"): &meta.Description,
@@ -1020,6 +1048,7 @@ func (ctx *evalContext) pf(
k("exclusive"): &attr.Exclusive, k("exclusive"): &attr.Exclusive,
k("toyboxEarly"): &attr.Early, k("toyboxEarly"): &attr.Early,
k("minimal"): &attr.NoToolchain, k("minimal"): &attr.NoToolchain,
k("bootstrap"): &bootstrap,
k("checksum"): &kc, k("checksum"): &kc,
k("output"): &output, k("output"): &output,
@@ -1032,6 +1061,7 @@ func (ctx *evalContext) pf(
}); err != nil { }); err != nil {
return return
} }
attr.Std = !bootstrap
var inputsH, extraH P var inputsH, extraH P
if inputsH, err = toHandles(inputs); err != nil { if inputsH, err = toHandles(inputs); err != nil {
return return
@@ -1149,6 +1179,10 @@ func (ctx *evalContext) pf(
} }
} }
if helper == nil {
panic(HelperError(name))
}
v = cachedArtifact{&meta, ctx.t.New( v = cachedArtifact{&meta, ctx.t.New(
meta.Name, meta.Name,
meta.Version, meta.Version,