From 8e59ff98b5aa1637ed4f47d283b9d7844d0a1b06 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Wed, 21 Jan 2026 05:28:41 +0900 Subject: [PATCH] internal/rosa: include iana-etc This is used by some programs and will likely end up in the Rosa OS system image anyway. Signed-off-by: Ophestra --- internal/rosa/etc.go | 71 ++++++++++++++++++++++++++++++++++++++++--- internal/rosa/rosa.go | 2 +- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/internal/rosa/etc.go b/internal/rosa/etc.go index 9126bdd..25947c2 100644 --- a/internal/rosa/etc.go +++ b/internal/rosa/etc.go @@ -1,7 +1,10 @@ package rosa import ( + "errors" + "io" "os" + "syscall" "hakurei.app/internal/pkg" ) @@ -9,10 +12,13 @@ import ( // cureEtc contains deterministic elements of /etc, made available as part of // [Toolchain]. This silences test suites expecting certain standard files to be // available in /etc. -type cureEtc struct{} +type cureEtc struct { + // Optional via newIANAEtc. + iana pkg.Artifact +} // Cure writes hardcoded configuration to files under etc. -func (cureEtc) Cure(t *pkg.TContext) (err error) { +func (a cureEtc) Cure(t *pkg.FContext) (err error) { etc := t.GetWorkDir().Append("etc") if err = os.MkdirAll(etc.String(), 0700); err != nil { return @@ -36,6 +42,44 @@ nobody:x:65534: return } } + + if a.iana != nil { + iana, _ := t.GetArtifact(a.iana) + + buf := make([]byte, syscall.Getpagesize()<<3) + for _, name := range []string{ + "protocols", + "services", + } { + var dst, src *os.File + if dst, err = os.OpenFile( + etc.Append(name).String(), + syscall.O_CREAT|syscall.O_EXCL|syscall.O_WRONLY, + 0400, + ); err != nil { + return + } + + if src, err = os.Open( + iana.Append(name).String(), + ); err != nil { + _ = dst.Close() + return + } + + _, err = io.CopyBuffer(dst, src, buf) + closeErrs := [...]error{ + dst.Close(), + src.Close(), + } + if err != nil { + return + } else if err = errors.Join(closeErrs[:]...); err != nil { + return + } + } + } + return os.Chmod(etc.String(), 0500) } @@ -45,8 +89,27 @@ func (cureEtc) Kind() pkg.Kind { return kindEtc } // Params is a noop. func (cureEtc) Params(*pkg.IContext) {} -// Dependencies returns a nil slice. -func (cureEtc) Dependencies() []pkg.Artifact { return nil } +// Dependencies returns a slice containing the backing iana-etc release. +func (a cureEtc) Dependencies() []pkg.Artifact { + if a.iana != nil { + return []pkg.Artifact{a.iana} + } + return nil +} // String returns a hardcoded reporting name. func (cureEtc) String() string { return "cure-etc" } + +// newIANAEtc returns an unpacked iana-etc release. +func newIANAEtc() pkg.Artifact { + const ( + version = "20251215" + checksum = "kvKz0gW_rGG5QaNK9ZWmWu1IEgYAdmhj_wR7DYrh3axDfIql_clGRHmelP7525NJ" + ) + return pkg.NewHTTPGetTar( + nil, "https://github.com/Mic92/iana-etc/releases/download/"+ + version+"/iana-etc-"+version+".tar.gz", + mustDecode(checksum), + pkg.TarGzip, + ) +} diff --git a/internal/rosa/rosa.go b/internal/rosa/rosa.go index 6c4d585..1351965 100644 --- a/internal/rosa/rosa.go +++ b/internal/rosa/rosa.go @@ -216,7 +216,7 @@ ln -vs ../usr/bin /work/bin boot := t - 1 musl, compilerRT, runtimes, clang := boot.NewLLVM() support = slices.Concat([]pkg.Artifact{ - cureEtc{}, + cureEtc{newIANAEtc()}, musl, compilerRT, runtimes,