Compare commits
71 Commits
1d5d063d6a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
0cf0e18e35
|
|||
|
ee5c0dd135
|
|||
|
92c48d82e2
|
|||
|
c79a4fe7f8
|
|||
|
0aeb2bccfb
|
|||
|
50e079b99f
|
|||
|
fb2cb5005a
|
|||
|
6e73c28a92
|
|||
|
2c08aa3674
|
|||
|
1af73ae7b4
|
|||
|
c9aa5e04b1
|
|||
|
70a38bd3b0
|
|||
|
533b15da89
|
|||
|
a890e1d0e5
|
|||
|
e3520835bb
|
|||
|
0e56847754
|
|||
|
145d03b366
|
|||
|
2886228d40
|
|||
|
e1e499b79e
|
|||
|
65b7dd8b37
|
|||
|
8d72b9e5bd
|
|||
|
8a3c3d145a
|
|||
|
575ef307ad
|
|||
|
d4144fcf7f
|
|||
|
bad66facbc
|
|||
|
4aba014eac
|
|||
|
779ba994ce
|
|||
|
917be2de93
|
|||
|
9aad98d409
|
|||
|
b0d06b67dc
|
|||
|
089100f29d
|
|||
|
dfd26abf6c
|
|||
|
617ee21647
|
|||
|
15cdb37ec2
|
|||
|
1f0bdc7aca
|
|||
|
e3ffe85670
|
|||
|
f4403ba5cd
|
|||
|
5a26895a22
|
|||
|
09d9f766a9
|
|||
|
6558169666
|
|||
|
cccf970c57
|
|||
|
57ffb21690
|
|||
|
9c560b455a
|
|||
|
4c7c0fbfc6
|
|||
|
18b3b7904e
|
|||
|
fefefdf734
|
|||
|
b84bb09a80
|
|||
|
337bf20f50
|
|||
|
1cb792cf6e
|
|||
|
b2b40b07e8
|
|||
|
da11b26ec1
|
|||
|
024489e800
|
|||
|
0f795712b0
|
|||
|
7e2210ff71
|
|||
|
a71a008f3c
|
|||
|
162265b47e
|
|||
|
3fa7ac04e4
|
|||
|
bf2867d653
|
|||
|
ec0f0f6507
|
|||
|
a77a802955
|
|||
|
4407e14dfc
|
|||
|
e024d3184a
|
|||
|
8e1bf00c2d
|
|||
|
b111e22050
|
|||
|
1fa458c0be
|
|||
|
2c7ae67a67
|
|||
|
3826621b21
|
|||
|
041b505c2e
|
|||
|
e6debce649
|
|||
|
aa26b86fce
|
|||
|
a57a8fd5d8
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,7 +8,7 @@
|
||||
# go generate
|
||||
/cmd/hakurei/LICENSE
|
||||
/cmd/mbf/internal/pkgserver/ui/static
|
||||
/internal/pkg/testdata/testtool
|
||||
/internal/pkg/internal/testtool/testtool
|
||||
/internal/rosa/hakurei_current.tar.gz
|
||||
|
||||
# cmd/dist default destination
|
||||
|
||||
5
all.sh
5
all.sh
@@ -1,6 +1,3 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
TOOLCHAIN_VERSION="$(go version)"
|
||||
cd "$(dirname -- "$0")/"
|
||||
echo "# Building cmd/dist using ${TOOLCHAIN_VERSION}."
|
||||
go run -v --tags=dist ./cmd/dist
|
||||
HAKUREI_DIST_MAKE='' exec "$(dirname -- "$0")/cmd/dist/dist.sh"
|
||||
|
||||
@@ -4,15 +4,23 @@ import "strings"
|
||||
|
||||
const (
|
||||
// SpecialOverlayEscape is the escape string for overlay mount options.
|
||||
//
|
||||
// Deprecated: This is no longer used and will be removed in 0.5.
|
||||
SpecialOverlayEscape = `\`
|
||||
// SpecialOverlayOption is the separator string between overlay mount options.
|
||||
//
|
||||
// Deprecated: This is no longer used and will be removed in 0.5.
|
||||
SpecialOverlayOption = ","
|
||||
// SpecialOverlayPath is the separator string between overlay paths.
|
||||
//
|
||||
// Deprecated: This is no longer used and will be removed in 0.5.
|
||||
SpecialOverlayPath = ":"
|
||||
)
|
||||
|
||||
// EscapeOverlayDataSegment escapes a string for formatting into the data
|
||||
// argument of an overlay mount system call.
|
||||
//
|
||||
// Deprecated: This is no longer used and will be removed in 0.5.
|
||||
func EscapeOverlayDataSegment(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
|
||||
10
cmd/dist/dist.sh
vendored
Executable file
10
cmd/dist/dist.sh
vendored
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
TOOLCHAIN_VERSION="$(go version)"
|
||||
cd "$(dirname -- "$0")/../.."
|
||||
echo "Building cmd/dist using ${TOOLCHAIN_VERSION}."
|
||||
FLAGS=''
|
||||
if test -n "$VERBOSE"; then
|
||||
FLAGS="$FLAGS -v"
|
||||
fi
|
||||
go run $FLAGS --tags=dist ./cmd/dist
|
||||
30
cmd/dist/main.go
vendored
30
cmd/dist/main.go
vendored
@@ -42,14 +42,19 @@ func mustRun(ctx context.Context, name string, arg ...string) {
|
||||
var comp []byte
|
||||
|
||||
func main() {
|
||||
fmt.Println()
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("# ")
|
||||
log.SetPrefix("")
|
||||
|
||||
verbose := os.Getenv("VERBOSE") != ""
|
||||
runTests := os.Getenv("HAKUREI_DIST_MAKE") == ""
|
||||
version := getenv("HAKUREI_VERSION", "untagged")
|
||||
prefix := getenv("PREFIX", "/usr")
|
||||
destdir := getenv("DESTDIR", "dist")
|
||||
|
||||
if verbose {
|
||||
log.Println()
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(destdir, 0755); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -76,12 +81,17 @@ func main() {
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer cancel()
|
||||
|
||||
log.Println("Building hakurei.")
|
||||
verboseFlag := "-v"
|
||||
if !verbose {
|
||||
verboseFlag = "-buildvcs=false"
|
||||
}
|
||||
|
||||
log.Printf("Building hakurei for %s/%s.", runtime.GOOS, runtime.GOARCH)
|
||||
mustRun(ctx, "go", "generate", "./...")
|
||||
mustRun(
|
||||
ctx, "go", "build",
|
||||
"-trimpath",
|
||||
"-v", "-o", s,
|
||||
verboseFlag, "-o", s,
|
||||
"-ldflags=-s -w "+
|
||||
"-buildid= -linkmode external -extldflags=-static "+
|
||||
"-X hakurei.app/internal/info.buildVersion="+version+" "+
|
||||
@@ -90,17 +100,19 @@ func main() {
|
||||
"-X main.hakureiPath="+prefix+"/bin/hakurei",
|
||||
"./...",
|
||||
)
|
||||
fmt.Println()
|
||||
log.Println()
|
||||
|
||||
log.Println("Testing Hakurei.")
|
||||
if runTests {
|
||||
log.Println("##### Testing Hakurei.")
|
||||
mustRun(
|
||||
ctx, "go", "test",
|
||||
"-ldflags=-buildid= -linkmode external -extldflags=-static",
|
||||
"./...",
|
||||
)
|
||||
fmt.Println()
|
||||
log.Println()
|
||||
}
|
||||
|
||||
log.Println("Creating distribution.")
|
||||
log.Println("##### Creating distribution.")
|
||||
const suffix = ".tar.gz"
|
||||
distName := "hakurei-" + version + "-" + runtime.GOARCH
|
||||
var f *os.File
|
||||
@@ -121,7 +133,7 @@ func main() {
|
||||
}()
|
||||
|
||||
h := sha512.New()
|
||||
gw := gzip.NewWriter(io.MultiWriter(f, h))
|
||||
gw, _ := gzip.NewWriterLevel(io.MultiWriter(f, h), gzip.BestCompression)
|
||||
tw := tar.NewWriter(gw)
|
||||
|
||||
mustWriteHeader := func(name string, size int64, mode os.FileMode) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/container"
|
||||
"hakurei.app/internal/pkg"
|
||||
"hakurei.app/message"
|
||||
)
|
||||
@@ -20,7 +21,14 @@ type cache struct {
|
||||
c *pkg.Cache
|
||||
|
||||
cures, jobs int
|
||||
hostAbstract, idle bool
|
||||
// Primarily to work around missing landlock LSM.
|
||||
hostAbstract bool
|
||||
// Set SCHED_IDLE.
|
||||
idle bool
|
||||
// Unset [pkg.CSuppressInit].
|
||||
verboseInit bool
|
||||
// Loaded artifact of [rosa.QEMU].
|
||||
qemu pkg.Artifact
|
||||
|
||||
base string
|
||||
}
|
||||
@@ -45,6 +53,9 @@ func (cache *cache) open() (err error) {
|
||||
if cache.hostAbstract {
|
||||
flags |= pkg.CHostAbstract
|
||||
}
|
||||
if !cache.verboseInit {
|
||||
flags |= pkg.CSuppressInit
|
||||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
@@ -70,6 +81,39 @@ func (cache *cache) open() (err error) {
|
||||
cache.jobs,
|
||||
base,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
done <- struct{}{}
|
||||
|
||||
if cache.qemu != nil {
|
||||
var pathname *check.Absolute
|
||||
pathname, _, err = cache.c.Cure(cache.qemu)
|
||||
if err != nil {
|
||||
cache.c.Close()
|
||||
return
|
||||
}
|
||||
|
||||
pkg.RegisterArch("riscv64", container.BinfmtEntry{
|
||||
Offset: 0,
|
||||
Magic: "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00",
|
||||
Mask: "\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff",
|
||||
Interpreter: pathname.Append(
|
||||
"system/bin",
|
||||
"qemu-riscv64",
|
||||
),
|
||||
})
|
||||
pkg.RegisterArch("arm64", container.BinfmtEntry{
|
||||
Offset: 0,
|
||||
Magic: "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00",
|
||||
Mask: "\xff\xff\xff\xff\xff\xff\xff\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff",
|
||||
Interpreter: pathname.Append(
|
||||
"system/bin",
|
||||
"qemu-aarch64",
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -67,9 +67,13 @@ func main() {
|
||||
|
||||
var (
|
||||
flagQuiet bool
|
||||
flagQEMU bool
|
||||
flagArch string
|
||||
flagCheck bool
|
||||
flagLTO bool
|
||||
|
||||
flagCrossOverride int
|
||||
|
||||
addr net.UnixAddr
|
||||
)
|
||||
c := command.New(os.Stderr, log.Printf, "mbf", func([]string) error {
|
||||
@@ -93,13 +97,36 @@ func main() {
|
||||
if !flagLTO {
|
||||
flags |= rosa.OptLLVMNoLTO
|
||||
}
|
||||
rosa.DropCaches(flags)
|
||||
rosa.DropCaches("", flags)
|
||||
cross := flagArch != "" && flagArch != runtime.GOARCH
|
||||
if flagQEMU || cross {
|
||||
cm.qemu = rosa.Std.Load(rosa.QEMU)
|
||||
}
|
||||
|
||||
if cross {
|
||||
if flagCrossOverride != -1 {
|
||||
flags = flagCrossOverride
|
||||
}
|
||||
|
||||
rosa.DropCaches(flagArch, flags)
|
||||
if !rosa.HasStage0() {
|
||||
return pkg.UnsupportedArchError(flagArch)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}).Flag(
|
||||
&flagQuiet,
|
||||
"q", command.BoolFlag(false),
|
||||
"Do not print cure messages",
|
||||
).Flag(
|
||||
&flagQEMU,
|
||||
"register", command.BoolFlag(false),
|
||||
"Enable additional target architectures",
|
||||
).Flag(
|
||||
&flagArch,
|
||||
"arch", command.StringFlag(runtime.GOARCH),
|
||||
"Target architecture",
|
||||
).Flag(
|
||||
&flagLTO,
|
||||
"lto", command.BoolFlag(false),
|
||||
@@ -108,6 +135,14 @@ func main() {
|
||||
&flagCheck,
|
||||
"check", command.BoolFlag(true),
|
||||
"Run test suites",
|
||||
).Flag(
|
||||
&flagCrossOverride,
|
||||
"cross-flags", command.IntFlag(-1),
|
||||
"Override non-native target preset flags",
|
||||
).Flag(
|
||||
&cm.verboseInit,
|
||||
"v", command.BoolFlag(false),
|
||||
"Do not suppress verbose output from init",
|
||||
).Flag(
|
||||
&cm.cures,
|
||||
"cures", command.IntFlag(0),
|
||||
@@ -471,6 +506,9 @@ func main() {
|
||||
flagExport string
|
||||
flagRemote bool
|
||||
flagNoReply bool
|
||||
|
||||
flagBoot bool
|
||||
flagStd bool
|
||||
)
|
||||
c.NewCommand(
|
||||
"cure",
|
||||
@@ -484,11 +522,18 @@ func main() {
|
||||
return fmt.Errorf("unknown artifact %q", args[0])
|
||||
}
|
||||
|
||||
t := rosa.Std
|
||||
if flagBoot {
|
||||
t -= 2
|
||||
} else if flagStd {
|
||||
t -= 1
|
||||
}
|
||||
|
||||
switch {
|
||||
default:
|
||||
var pathname *check.Absolute
|
||||
err := cm.Do(func(cache *pkg.Cache) (err error) {
|
||||
pathname, _, err = cache.Cure(rosa.Std.Load(p))
|
||||
pathname, _, err = cache.Cure(t.Load(p))
|
||||
return
|
||||
})
|
||||
if err != nil {
|
||||
@@ -541,7 +586,7 @@ func main() {
|
||||
return cm.Do(func(cache *pkg.Cache) error {
|
||||
return cache.EnterExec(
|
||||
ctx,
|
||||
rosa.Std.Load(p),
|
||||
t.Load(p),
|
||||
true, os.Stdin, os.Stdout, os.Stderr,
|
||||
rosa.AbsSystem.Append("bin", "mksh"),
|
||||
"sh",
|
||||
@@ -553,7 +598,7 @@ func main() {
|
||||
if flagNoReply {
|
||||
flags |= remoteNoReply
|
||||
}
|
||||
a := rosa.Std.Load(p)
|
||||
a := t.Load(p)
|
||||
pathname, err := cureRemote(ctx, &addr, a, flags)
|
||||
if !flagNoReply && err == nil {
|
||||
log.Println(pathname)
|
||||
@@ -591,6 +636,14 @@ func main() {
|
||||
&flagNoReply,
|
||||
"no-reply", command.BoolFlag(false),
|
||||
"Do not receive a reply from the daemon",
|
||||
).Flag(
|
||||
&flagBoot,
|
||||
"boot", command.BoolFlag(false),
|
||||
"Build on the stage0 toolchain",
|
||||
).Flag(
|
||||
&flagStd,
|
||||
"std", command.BoolFlag(false),
|
||||
"Build on the intermediate toolchain",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -692,6 +745,7 @@ func main() {
|
||||
z.Hostname = "localhost"
|
||||
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
|
||||
z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||
z.Quiet = !cm.verboseInit
|
||||
if s, ok := os.LookupEnv("TERM"); ok {
|
||||
z.Env = append(z.Env, "TERM="+s)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
rosa.DropCaches(rosa.OptLLVMNoLTO)
|
||||
rosa.DropCaches("", rosa.OptLLVMNoLTO)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,14 @@
|
||||
};
|
||||
|
||||
virtualisation = {
|
||||
# Hopefully reduces spurious test failures:
|
||||
memorySize = if pkgs.stdenv.hostPlatform.is32bit then 2046 else 8192;
|
||||
|
||||
diskSize = 6 * 1024;
|
||||
|
||||
qemu.options = [
|
||||
# Increase test performance:
|
||||
"-smp 8"
|
||||
"-smp 16"
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ testers.nixosTest {
|
||||
# For go tests:
|
||||
(pkgs.writeShellScriptBin "sharefs-workload-hakurei-tests" ''
|
||||
cp -r "${self.packages.${system}.hakurei.src}" "/sdcard/hakurei" && cd "/sdcard/hakurei"
|
||||
${fhs}/bin/hakurei-fhs -c 'CC="clang -O3 -Werror" go test ./...'
|
||||
${fhs}/bin/hakurei-fhs -c 'ROSA_SKIP_BINFMT=1 CC="clang -O3 -Werror" go test ./...'
|
||||
'')
|
||||
];
|
||||
|
||||
|
||||
46
container/binfmt.go
Normal file
46
container/binfmt.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"hakurei.app/check"
|
||||
)
|
||||
|
||||
// escapeBinfmt escapes magic/mask sequences in a [BinfmtEntry].
|
||||
func escapeBinfmt(buf *strings.Builder, s string) string {
|
||||
const lowerhex = "0123456789abcdef"
|
||||
|
||||
buf.Reset()
|
||||
for _, c := range unsafe.Slice(unsafe.StringData(s), len(s)) {
|
||||
switch c {
|
||||
case 0, '\\', ':':
|
||||
buf.WriteString(`\x`)
|
||||
buf.WriteByte(lowerhex[c>>4])
|
||||
buf.WriteByte(lowerhex[c&0xf])
|
||||
|
||||
default:
|
||||
buf.WriteByte(c)
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// BinfmtEntry is an entry to be registered by the init process.
|
||||
type BinfmtEntry struct {
|
||||
// The offset of the magic/mask in the file, counted in bytes.
|
||||
Offset byte
|
||||
// The byte sequence binfmt_misc is matching for.
|
||||
Magic string
|
||||
// An (optional, defaults to all 0xff) mask.
|
||||
Mask string
|
||||
// The program that should be invoked with the binary as first argument.
|
||||
Interpreter *check.Absolute
|
||||
}
|
||||
|
||||
// Valid returns whether e can be registered into the kernel.
|
||||
func (e *BinfmtEntry) Valid() bool {
|
||||
return e != nil &&
|
||||
int(e.Offset)+max(len(e.Magic), len(e.Mask)) < 128 &&
|
||||
e.Interpreter != nil && len(e.Interpreter.String()) < 128
|
||||
}
|
||||
62
container/binfmt_test.go
Normal file
62
container/binfmt_test.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package container
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"hakurei.app/fhs"
|
||||
)
|
||||
|
||||
func TestEscapeBinfmt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
magic string
|
||||
want string
|
||||
}{
|
||||
{"packed DOS applications", "\x0eDEX", "\x0eDEX"},
|
||||
|
||||
{"riscv64 magic",
|
||||
"\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00",
|
||||
"\x7fELF\x02\x01\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\x02\\x00\xf3\\x00"},
|
||||
{"riscv64 mask",
|
||||
"\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff",
|
||||
"\xff\xff\xff\xff\xff\xff\xff\\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
got := escapeBinfmt(new(strings.Builder), tc.magic)
|
||||
if got != tc.want {
|
||||
t.Errorf("escapeBinfmt: %q, want %q", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBinfmtEntry(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
e BinfmtEntry
|
||||
valid bool
|
||||
}{
|
||||
{"zero", BinfmtEntry{}, false},
|
||||
{"large offset", BinfmtEntry{Offset: 128}, false},
|
||||
{"long magic", BinfmtEntry{Magic: strings.Repeat("\x00", 128)}, false},
|
||||
{"long mask", BinfmtEntry{Mask: strings.Repeat("\x00", 128)}, false},
|
||||
{"valid", BinfmtEntry{Interpreter: fhs.AbsRoot}, true},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if tc.e.Valid() != tc.valid {
|
||||
t.Errorf("Valid: %v", !tc.valid)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ const (
|
||||
CAP_SETPCAP = 0x8
|
||||
CAP_NET_ADMIN = 0xc
|
||||
CAP_DAC_OVERRIDE = 0x1
|
||||
CAP_SETFCAP = 0x1f
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
@@ -67,6 +67,9 @@ type (
|
||||
// Copied to the underlying [exec.Cmd].
|
||||
WaitDelay time.Duration
|
||||
|
||||
// Suppress verbose output of init.
|
||||
Quiet bool
|
||||
|
||||
cmd *exec.Cmd
|
||||
ctx context.Context
|
||||
msg message.Msg
|
||||
@@ -88,12 +91,20 @@ type (
|
||||
// Time to wait for processes lingering after the initial process terminates.
|
||||
AdoptWaitDelay time.Duration
|
||||
|
||||
// Map uid/gid 0 in the init process. Requires [FstypeProc] attached to
|
||||
// [fhs.Proc] in the container filesystem.
|
||||
InitAsRoot bool
|
||||
// Mapped Uid in user namespace.
|
||||
Uid int
|
||||
// Mapped Gid in user namespace.
|
||||
Gid int
|
||||
// Hostname value in UTS namespace.
|
||||
Hostname string
|
||||
// Register binfmt_misc entries.
|
||||
Binfmt []BinfmtEntry
|
||||
// Alternative pathname to attach binfmt_misc filesystem. The zero value
|
||||
// requires [FstypeProc] to be made available at [fhs.Proc].
|
||||
BinfmtPath *check.Absolute
|
||||
// Sequential container setup ops.
|
||||
*Ops
|
||||
|
||||
@@ -213,6 +224,9 @@ func (p *Container) Start() error {
|
||||
if p.cmd.Process != nil {
|
||||
return errors.New("container: already started")
|
||||
}
|
||||
if !p.InitAsRoot && len(p.Binfmt) > 0 {
|
||||
return errors.New("container: init as root required, but not enabled")
|
||||
}
|
||||
|
||||
if err := ensureCloseOnExec(); err != nil {
|
||||
return err
|
||||
@@ -283,6 +297,18 @@ func (p *Container) Start() error {
|
||||
if !p.HostNet {
|
||||
p.cmd.SysProcAttr.Cloneflags |= CLONE_NEWNET
|
||||
}
|
||||
if p.InitAsRoot {
|
||||
p.cmd.SysProcAttr.AmbientCaps = append(p.cmd.SysProcAttr.AmbientCaps,
|
||||
// mappings during init as root
|
||||
CAP_SETFCAP,
|
||||
)
|
||||
|
||||
if !p.SeccompDisable &&
|
||||
len(p.SeccompRules) == 0 &&
|
||||
p.SeccompPresets&std.PresetDenyNS != 0 {
|
||||
return errors.New("container: as root requires late namespace creation")
|
||||
}
|
||||
}
|
||||
|
||||
// place setup pipe before user supplied extra files, this is later restored by init
|
||||
if r, w, err := os.Pipe(); err != nil {
|
||||
@@ -342,8 +368,6 @@ func (p *Container) Start() error {
|
||||
Err: ENOSYS,
|
||||
Origin: true,
|
||||
}
|
||||
} else {
|
||||
p.msg.Verbosef("landlock abi version %d", abi)
|
||||
}
|
||||
|
||||
if rulesetFd, err := rulesetAttr.Create(0); err != nil {
|
||||
@@ -353,7 +377,6 @@ func (p *Container) Start() error {
|
||||
Err: err,
|
||||
}
|
||||
} else {
|
||||
p.msg.Verbosef("enforcing landlock ruleset %s", rulesetAttr)
|
||||
if err = landlock.RestrictSelf(rulesetFd, 0); err != nil {
|
||||
_ = Close(rulesetFd)
|
||||
return &StartError{
|
||||
@@ -410,7 +433,6 @@ func (p *Container) Start() error {
|
||||
}
|
||||
}
|
||||
|
||||
p.msg.Verbose("starting container init")
|
||||
if err := p.cmd.Start(); err != nil {
|
||||
return &StartError{
|
||||
Step: "start container init",
|
||||
@@ -481,7 +503,6 @@ func (p *Container) Serve() (err error) {
|
||||
}
|
||||
|
||||
case <-done:
|
||||
p.msg.Verbose("setup payload took", time.Since(t))
|
||||
return
|
||||
}
|
||||
}(p.setup[1])
|
||||
@@ -491,7 +512,7 @@ func (p *Container) Serve() (err error) {
|
||||
Getuid(),
|
||||
Getgid(),
|
||||
len(p.ExtraFiles),
|
||||
p.msg.IsVerbose(),
|
||||
p.msg.IsVerbose() && !p.Quiet,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/command"
|
||||
@@ -233,6 +235,9 @@ func earlyMnt(mnt ...*vfs.MountInfoEntry) func(*testing.T, context.Context) []*v
|
||||
return func(*testing.T, context.Context) []*vfs.MountInfoEntry { return mnt }
|
||||
}
|
||||
|
||||
//go:linkname toHost hakurei.app/container.toHost
|
||||
func toHost(name string) string
|
||||
|
||||
var containerTestCases = []struct {
|
||||
name string
|
||||
filter bool
|
||||
@@ -332,13 +337,15 @@ var containerTestCases = []struct {
|
||||
func(t *testing.T, ctx context.Context) []*vfs.MountInfoEntry {
|
||||
return []*vfs.MountInfoEntry{
|
||||
ent("/", hst.PrivateTmp, "rw", "overlay", "overlay",
|
||||
"rw,lowerdir="+
|
||||
container.InternalToHostOvlEscape(ctx.Value(testVal("lower0")).(*check.Absolute).String())+":"+
|
||||
container.InternalToHostOvlEscape(ctx.Value(testVal("lower1")).(*check.Absolute).String())+
|
||||
"rw"+
|
||||
",lowerdir+="+
|
||||
toHost(ctx.Value(testVal("lower0")).(*check.Absolute).String())+
|
||||
",lowerdir+="+
|
||||
toHost(ctx.Value(testVal("lower1")).(*check.Absolute).String())+
|
||||
",upperdir="+
|
||||
container.InternalToHostOvlEscape(ctx.Value(testVal("upper")).(*check.Absolute).String())+
|
||||
toHost(ctx.Value(testVal("upper")).(*check.Absolute).String())+
|
||||
",workdir="+
|
||||
container.InternalToHostOvlEscape(ctx.Value(testVal("work")).(*check.Absolute).String())+
|
||||
toHost(ctx.Value(testVal("work")).(*check.Absolute).String())+
|
||||
",redirect_dir=nofollow,uuid=on,userxattr"),
|
||||
}
|
||||
},
|
||||
@@ -388,9 +395,11 @@ var containerTestCases = []struct {
|
||||
func(t *testing.T, ctx context.Context) []*vfs.MountInfoEntry {
|
||||
return []*vfs.MountInfoEntry{
|
||||
ent("/", hst.PrivateTmp, "rw", "overlay", "overlay",
|
||||
"ro,lowerdir="+
|
||||
container.InternalToHostOvlEscape(ctx.Value(testVal("lower0")).(*check.Absolute).String())+":"+
|
||||
container.InternalToHostOvlEscape(ctx.Value(testVal("lower1")).(*check.Absolute).String())+
|
||||
"ro"+
|
||||
",lowerdir+="+
|
||||
toHost(ctx.Value(testVal("lower0")).(*check.Absolute).String())+
|
||||
",lowerdir+="+
|
||||
toHost(ctx.Value(testVal("lower1")).(*check.Absolute).String())+
|
||||
",redirect_dir=nofollow,userxattr"),
|
||||
}
|
||||
},
|
||||
@@ -400,39 +409,11 @@ var containerTestCases = []struct {
|
||||
func TestContainer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("cancel", testContainerCancel(nil, func(t *testing.T, c *container.Container) {
|
||||
wantErr := context.Canceled
|
||||
wantExitCode := 0
|
||||
if err := c.Wait(); !reflect.DeepEqual(err, wantErr) {
|
||||
if m, ok := container.InternalMessageFromError(err); ok {
|
||||
t.Error(m)
|
||||
}
|
||||
t.Errorf("Wait: error = %#v, want %#v", err, wantErr)
|
||||
}
|
||||
if ps := c.ProcessState(); ps == nil {
|
||||
t.Errorf("ProcessState unexpectedly returned nil")
|
||||
} else if code := ps.ExitCode(); code != wantExitCode {
|
||||
t.Errorf("ExitCode: %d, want %d", code, wantExitCode)
|
||||
}
|
||||
}))
|
||||
|
||||
t.Run("forward", testContainerCancel(func(c *container.Container) {
|
||||
c.ForwardCancel = true
|
||||
}, func(t *testing.T, c *container.Container) {
|
||||
var exitError *exec.ExitError
|
||||
if err := c.Wait(); !errors.As(err, &exitError) {
|
||||
if m, ok := container.InternalMessageFromError(err); ok {
|
||||
t.Error(m)
|
||||
}
|
||||
t.Errorf("Wait: error = %v", err)
|
||||
}
|
||||
if code := exitError.ExitCode(); code != blockExitCodeInterrupt {
|
||||
t.Errorf("ExitCode: %d, want %d", code, blockExitCodeInterrupt)
|
||||
}
|
||||
}))
|
||||
|
||||
var suffix string
|
||||
runTests:
|
||||
for i, tc := range containerTestCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_suffix := suffix
|
||||
t.Run(tc.name+_suffix, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
wantOps, wantOpsCtx := tc.ops(t)
|
||||
@@ -456,6 +437,8 @@ func TestContainer(t *testing.T) {
|
||||
c.SeccompDisable = !tc.filter
|
||||
c.RetainSession = tc.session
|
||||
c.HostNet = tc.net
|
||||
c.InitAsRoot = _suffix != ""
|
||||
c.Env = append(c.Env, "HAKUREI_TEST_SUFFIX="+_suffix)
|
||||
if info.CanDegrade {
|
||||
if _, err := landlock.GetABI(); err != nil {
|
||||
if !errors.Is(err, syscall.ENOSYS) {
|
||||
@@ -465,6 +448,9 @@ func TestContainer(t *testing.T) {
|
||||
t.Log("Landlock LSM is unavailable, enabling HostAbstract")
|
||||
}
|
||||
}
|
||||
if c.InitAsRoot {
|
||||
c.SeccompPresets &= ^std.PresetDenyNS
|
||||
}
|
||||
|
||||
c.
|
||||
Readonly(check.MustAbs(pathReadonly), 0755).
|
||||
@@ -533,6 +519,11 @@ func TestContainer(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if suffix == "" {
|
||||
suffix = " as root"
|
||||
goto runTests
|
||||
}
|
||||
}
|
||||
|
||||
func ent(root, target, vfsOptstr, fsType, source, fsOptstr string) *vfs.MountInfoEntry {
|
||||
@@ -555,11 +546,10 @@ func hostnameFromTestCase(name string) string {
|
||||
}
|
||||
|
||||
func testContainerCancel(
|
||||
t *testing.T,
|
||||
containerExtra func(c *container.Container),
|
||||
waitCheck func(t *testing.T, c *container.Container),
|
||||
) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Parallel()
|
||||
waitCheck func(ps *os.ProcessState, waitErr error),
|
||||
) {
|
||||
ctx, cancel := context.WithCancel(t.Context())
|
||||
|
||||
c := helperNewContainer(ctx, "block")
|
||||
@@ -569,25 +559,36 @@ func testContainerCancel(
|
||||
}
|
||||
|
||||
ready := make(chan struct{})
|
||||
if r, w, err := os.Pipe(); err != nil {
|
||||
var waitErr error
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatalf("cannot pipe: %v", err)
|
||||
} else {
|
||||
}
|
||||
|
||||
c.ExtraFiles = append(c.ExtraFiles, w)
|
||||
go func() {
|
||||
defer close(ready)
|
||||
if _, err = r.Read(make([]byte, 1)); err != nil {
|
||||
panic(err.Error())
|
||||
if _, _err := r.Read(make([]byte, 1)); _err != nil {
|
||||
panic(_err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if err := c.Start(); err != nil {
|
||||
if err = c.Start(); err != nil {
|
||||
if m, ok := container.InternalMessageFromError(err); ok {
|
||||
t.Fatal(m)
|
||||
} else {
|
||||
t.Fatalf("cannot start container: %v", err)
|
||||
}
|
||||
} else if err = c.Serve(); err != nil {
|
||||
}
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
waitErr = c.Wait()
|
||||
_ = r.SetReadDeadline(time.Now())
|
||||
}()
|
||||
|
||||
if err = c.Serve(); err != nil {
|
||||
if m, ok := container.InternalMessageFromError(err); ok {
|
||||
t.Error(m)
|
||||
} else {
|
||||
@@ -596,8 +597,67 @@ func testContainerCancel(
|
||||
}
|
||||
<-ready
|
||||
cancel()
|
||||
waitCheck(t, c)
|
||||
<-done
|
||||
waitCheck(c.ProcessState(), waitErr)
|
||||
}
|
||||
|
||||
func TestForward(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
f := func(ps *os.ProcessState, waitErr error) {
|
||||
var exitError *exec.ExitError
|
||||
if !errors.As(waitErr, &exitError) {
|
||||
if m, ok := container.InternalMessageFromError(waitErr); ok {
|
||||
t.Error(m)
|
||||
}
|
||||
t.Errorf("Wait: error = %v", waitErr)
|
||||
}
|
||||
if code := exitError.ExitCode(); code != blockExitCodeInterrupt {
|
||||
t.Errorf("ExitCode: %d, want %d", code, blockExitCodeInterrupt)
|
||||
}
|
||||
}
|
||||
t.Run("direct", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
testContainerCancel(t, func(c *container.Container) {
|
||||
c.ForwardCancel = true
|
||||
}, f)
|
||||
})
|
||||
t.Run("as root", func(t *testing.T) {
|
||||
testContainerCancel(t, func(c *container.Container) {
|
||||
c.ForwardCancel = true
|
||||
c.InitAsRoot = true
|
||||
c.Proc(fhs.AbsProc)
|
||||
}, f)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCancel(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
f := func(ps *os.ProcessState, waitErr error) {
|
||||
wantErr := context.Canceled
|
||||
if !reflect.DeepEqual(waitErr, wantErr) {
|
||||
if m, ok := container.InternalMessageFromError(waitErr); ok {
|
||||
t.Error(m)
|
||||
}
|
||||
t.Errorf("Wait: error = %#v, want %#v", waitErr, wantErr)
|
||||
}
|
||||
if ps == nil {
|
||||
t.Errorf("ProcessState unexpectedly returned nil")
|
||||
} else if code := ps.ExitCode(); code != 0 {
|
||||
t.Errorf("ExitCode: %d, want %d", code, 0)
|
||||
}
|
||||
}
|
||||
t.Run("direct", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
testContainerCancel(t, nil, f)
|
||||
})
|
||||
t.Run("as root", func(t *testing.T) {
|
||||
testContainerCancel(t, func(c *container.Container) {
|
||||
c.InitAsRoot = true
|
||||
c.Proc(fhs.AbsProc)
|
||||
}, f)
|
||||
})
|
||||
}
|
||||
|
||||
func TestContainerString(t *testing.T) {
|
||||
@@ -633,6 +693,8 @@ func init() {
|
||||
})
|
||||
|
||||
c.Command("container", command.UsageInternal, func(args []string) error {
|
||||
asRoot := os.Getenv("HAKUREI_TEST_SUFFIX") == " as root"
|
||||
|
||||
if len(args) != 1 {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
@@ -650,6 +712,66 @@ func init() {
|
||||
return fmt.Errorf("gid: %d, want %d", gid, tc.gid)
|
||||
}
|
||||
|
||||
// no attack surface increase during as root due to no_new_privs
|
||||
var wantBounding uintptr = 1
|
||||
asRootNot := " not"
|
||||
if !asRoot {
|
||||
wantBounding = 0
|
||||
asRootNot = ""
|
||||
}
|
||||
|
||||
const (
|
||||
PR_CAP_AMBIENT = 0x2f
|
||||
PR_CAP_AMBIENT_IS_SET = 0x1
|
||||
)
|
||||
for i := range container.LastCap(nil) + 1 {
|
||||
r, _, errno := syscall.Syscall(
|
||||
syscall.SYS_PRCTL,
|
||||
PR_CAP_AMBIENT,
|
||||
PR_CAP_AMBIENT_IS_SET,
|
||||
i,
|
||||
)
|
||||
if errno != 0 {
|
||||
return os.NewSyscallError("prctl", errno)
|
||||
}
|
||||
if r != 0 {
|
||||
return fmt.Errorf("capability %d in ambient set", i)
|
||||
}
|
||||
|
||||
r, _, errno = syscall.Syscall(
|
||||
syscall.SYS_PRCTL,
|
||||
syscall.PR_CAPBSET_READ,
|
||||
i,
|
||||
0,
|
||||
)
|
||||
if errno != 0 {
|
||||
return os.NewSyscallError("prctl", errno)
|
||||
}
|
||||
if r != wantBounding {
|
||||
return fmt.Errorf("capability %d%s in bounding set", i, asRootNot)
|
||||
}
|
||||
}
|
||||
|
||||
const _LINUX_CAPABILITY_VERSION_3 = 0x20080522
|
||||
var capData struct {
|
||||
effective uint32
|
||||
permitted uint32
|
||||
inheritable uint32
|
||||
}
|
||||
if _, _, errno := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(&struct {
|
||||
version uint32
|
||||
pid int32
|
||||
}{_LINUX_CAPABILITY_VERSION_3, 0})), uintptr(unsafe.Pointer(&capData)), 0); errno != 0 {
|
||||
return os.NewSyscallError("capget", errno)
|
||||
}
|
||||
|
||||
if max(capData.effective, capData.permitted, capData.inheritable) != 0 {
|
||||
return fmt.Errorf(
|
||||
"effective = %d, permitted = %d, inheritable = %d",
|
||||
capData.effective, capData.permitted, capData.inheritable,
|
||||
)
|
||||
}
|
||||
|
||||
wantHost := hostnameFromTestCase(tc.name)
|
||||
if host, err := os.Hostname(); err != nil {
|
||||
return fmt.Errorf("cannot get hostname: %v", err)
|
||||
@@ -767,7 +889,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
c.MustParse(os.Args[1:], func(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
})
|
||||
return
|
||||
|
||||
@@ -65,6 +65,8 @@ type syscallDispatcher interface {
|
||||
remount(msg message.Msg, target string, flags uintptr) error
|
||||
// mountTmpfs provides mountTmpfs.
|
||||
mountTmpfs(fsname, target string, flags uintptr, size int, perm os.FileMode) error
|
||||
// mountOverlay provides mountOverlay.
|
||||
mountOverlay(target string, options [][2]string) error
|
||||
// ensureFile provides ensureFile.
|
||||
ensureFile(name string, perm, pperm os.FileMode) error
|
||||
// mustLoopback provides mustLoopback.
|
||||
@@ -169,6 +171,9 @@ func (direct) remount(msg message.Msg, target string, flags uintptr) error {
|
||||
func (k direct) mountTmpfs(fsname, target string, flags uintptr, size int, perm os.FileMode) error {
|
||||
return mountTmpfs(k, fsname, target, flags, size, perm)
|
||||
}
|
||||
func (k direct) mountOverlay(target string, options [][2]string) error {
|
||||
return mountOverlay(target, options)
|
||||
}
|
||||
func (direct) ensureFile(name string, perm, pperm os.FileMode) error {
|
||||
return ensureFile(name, perm, pperm)
|
||||
}
|
||||
|
||||
@@ -468,6 +468,14 @@ func (k *kstub) mountTmpfs(fsname, target string, flags uintptr, size int, perm
|
||||
stub.CheckArg(k.Stub, "perm", perm, 4))
|
||||
}
|
||||
|
||||
func (k *kstub) mountOverlay(target string, options [][2]string) error {
|
||||
k.Helper()
|
||||
return k.Expects("mountOverlay").Error(
|
||||
stub.CheckArg(k.Stub, "target", target, 0),
|
||||
stub.CheckArgReflect(k.Stub, "options", options, 1),
|
||||
)
|
||||
}
|
||||
|
||||
func (k *kstub) ensureFile(name string, perm, pperm os.FileMode) error {
|
||||
k.Helper()
|
||||
return k.Expects("ensureFile").Error(
|
||||
|
||||
@@ -118,6 +118,10 @@ func errnoFallback(op, path string, err error) (syscall.Errno, *os.PathError) {
|
||||
|
||||
// mount wraps syscall.Mount for error handling.
|
||||
func mount(source, target, fstype string, flags uintptr, data string) error {
|
||||
if max(len(source), len(target), len(data))+1 > os.Getpagesize() {
|
||||
return &MountError{source, target, fstype, flags, data, syscall.ENOMEM}
|
||||
}
|
||||
|
||||
err := syscall.Mount(source, target, fstype, flags, data)
|
||||
if err == nil {
|
||||
return nil
|
||||
|
||||
@@ -11,11 +11,13 @@ import (
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
. "syscall"
|
||||
"time"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/container/seccomp"
|
||||
"hakurei.app/ext"
|
||||
"hakurei.app/fhs"
|
||||
@@ -182,23 +184,33 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
||||
cancel()
|
||||
}
|
||||
|
||||
uid, gid := param.Uid, param.Gid
|
||||
if param.InitAsRoot {
|
||||
uid, gid = 0, 0
|
||||
}
|
||||
|
||||
// write uid/gid map here so parent does not need to set dumpable
|
||||
if err := k.setDumpable(ext.SUID_DUMP_USER); err != nil {
|
||||
k.fatalf(msg, "cannot set SUID_DUMP_USER: %v", err)
|
||||
}
|
||||
if err := k.writeFile(fhs.Proc+"self/uid_map",
|
||||
append([]byte{}, strconv.Itoa(param.Uid)+" "+strconv.Itoa(param.HostUid)+" 1\n"...),
|
||||
0); err != nil {
|
||||
if err := k.writeFile(
|
||||
fhs.Proc+"self/uid_map",
|
||||
[]byte(strconv.Itoa(uid)+" "+strconv.Itoa(param.HostUid)+" 1\n"),
|
||||
0,
|
||||
); err != nil {
|
||||
k.fatalf(msg, "%v", err)
|
||||
}
|
||||
if err := k.writeFile(fhs.Proc+"self/setgroups",
|
||||
if err := k.writeFile(
|
||||
fhs.Proc+"self/setgroups",
|
||||
[]byte("deny\n"),
|
||||
0); err != nil && !os.IsNotExist(err) {
|
||||
0,
|
||||
); err != nil && !os.IsNotExist(err) {
|
||||
k.fatalf(msg, "%v", err)
|
||||
}
|
||||
if err := k.writeFile(fhs.Proc+"self/gid_map",
|
||||
append([]byte{}, strconv.Itoa(param.Gid)+" "+strconv.Itoa(param.HostGid)+" 1\n"...),
|
||||
0); err != nil {
|
||||
[]byte(strconv.Itoa(gid)+" "+strconv.Itoa(param.HostGid)+" 1\n"),
|
||||
0,
|
||||
); err != nil {
|
||||
k.fatalf(msg, "%v", err)
|
||||
}
|
||||
if err := k.setDumpable(ext.SUID_DUMP_DISABLE); err != nil {
|
||||
@@ -223,6 +235,23 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
||||
state := &setupState{process: make(map[int]WaitStatus), Params: ¶m.Params, Msg: msg, Context: ctx}
|
||||
defer cancel()
|
||||
|
||||
if err := k.mount(SourceTmpfsRootfs, intermediateHostPath, FstypeTmpfs, MS_NODEV|MS_NOSUID, zeroString); err != nil {
|
||||
k.fatalf(msg, "cannot mount intermediate root: %v", optionalErrorUnwrap(err))
|
||||
}
|
||||
if err := k.chdir(intermediateHostPath); err != nil {
|
||||
k.fatalf(msg, "cannot enter intermediate host path: %v", err)
|
||||
}
|
||||
|
||||
if len(param.Binfmt) > 0 {
|
||||
for i, e := range param.Binfmt {
|
||||
if pathname, err := k.evalSymlinks(e.Interpreter.String()); err != nil {
|
||||
k.fatal(msg, err)
|
||||
} else if param.Binfmt[i].Interpreter, err = check.NewAbs(pathname); err != nil {
|
||||
k.fatal(msg, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* early is called right before pivot_root into intermediate root;
|
||||
this step is mostly for gathering information that would otherwise be
|
||||
difficult to obtain via library functions after pivot_root, and
|
||||
@@ -242,13 +271,6 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
||||
}
|
||||
}
|
||||
|
||||
if err := k.mount(SourceTmpfsRootfs, intermediateHostPath, FstypeTmpfs, MS_NODEV|MS_NOSUID, zeroString); err != nil {
|
||||
k.fatalf(msg, "cannot mount intermediate root: %v", optionalErrorUnwrap(err))
|
||||
}
|
||||
if err := k.chdir(intermediateHostPath); err != nil {
|
||||
k.fatalf(msg, "cannot enter intermediate host path: %v", err)
|
||||
}
|
||||
|
||||
if err := k.mkdir(sysrootDir, 0755); err != nil {
|
||||
k.fatalf(msg, "%v", err)
|
||||
}
|
||||
@@ -285,6 +307,48 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
||||
}
|
||||
}
|
||||
|
||||
if len(param.Binfmt) > 0 {
|
||||
const interpreter = "/interpreter"
|
||||
|
||||
if param.BinfmtPath == nil {
|
||||
param.BinfmtPath = fhs.AbsProcSys.Append("fs/binfmt_misc")
|
||||
}
|
||||
binfmt := sysrootPath + param.BinfmtPath.String()
|
||||
if err := k.mkdirAll(binfmt, 0); err != nil {
|
||||
k.fatal(msg, err)
|
||||
}
|
||||
if err := k.mount(
|
||||
SourceBinfmtMisc,
|
||||
binfmt,
|
||||
FstypeBinfmtMisc,
|
||||
MS_NOSUID|MS_NOEXEC|MS_NODEV,
|
||||
zeroString,
|
||||
); err != nil {
|
||||
k.fatal(msg, err)
|
||||
}
|
||||
|
||||
var buf strings.Builder
|
||||
buf.Grow(1920)
|
||||
|
||||
register := binfmt + "/register"
|
||||
for i, e := range param.Binfmt {
|
||||
if err := k.symlink(hostPath+e.Interpreter.String(), interpreter); err != nil {
|
||||
k.fatal(msg, err)
|
||||
} else if err = k.writeFile(register, []byte(":"+
|
||||
strconv.Itoa(i)+":"+
|
||||
"M:"+
|
||||
strconv.Itoa(int(e.Offset))+":"+
|
||||
escapeBinfmt(&buf, e.Magic)+":"+
|
||||
escapeBinfmt(&buf, e.Mask)+":"+
|
||||
interpreter+":"+
|
||||
"F"), 0); err != nil {
|
||||
k.fatal(msg, err)
|
||||
} else if err = k.remove(interpreter); err != nil {
|
||||
k.fatal(msg, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setup requiring host root complete at this point
|
||||
if err := k.mount(hostDir, hostDir, zeroString, MS_SILENT|MS_REC|MS_PRIVATE, zeroString); err != nil {
|
||||
k.fatalf(msg, "cannot make host root rprivate: %v", optionalErrorUnwrap(err))
|
||||
@@ -323,11 +387,19 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
||||
}
|
||||
}
|
||||
|
||||
var keepCaps []uintptr
|
||||
if param.Privileged {
|
||||
keepCaps = append(keepCaps, CAP_SYS_ADMIN, CAP_SETPCAP)
|
||||
}
|
||||
if param.InitAsRoot {
|
||||
keepCaps = append(keepCaps, CAP_SETFCAP)
|
||||
}
|
||||
|
||||
if err := k.capAmbientClearAll(); err != nil {
|
||||
k.fatalf(msg, "cannot clear the ambient capability set: %v", err)
|
||||
}
|
||||
for i := uintptr(0); i <= lastcap; i++ {
|
||||
if param.Privileged && i == CAP_SYS_ADMIN {
|
||||
for i := range lastcap + 1 {
|
||||
if slices.Contains(keepCaps, i) {
|
||||
continue
|
||||
}
|
||||
if err := k.capBoundingSetDrop(i); err != nil {
|
||||
@@ -336,20 +408,23 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
||||
}
|
||||
|
||||
var keep [2]uint32
|
||||
if param.Privileged {
|
||||
keep[capToIndex(CAP_SYS_ADMIN)] |= capToMask(CAP_SYS_ADMIN)
|
||||
for _, c := range keepCaps {
|
||||
keep[capToIndex(c)] |= capToMask(c)
|
||||
}
|
||||
|
||||
if err := k.capAmbientRaise(CAP_SYS_ADMIN); err != nil {
|
||||
k.fatalf(msg, "cannot raise CAP_SYS_ADMIN: %v", err)
|
||||
}
|
||||
}
|
||||
if err := k.capset(
|
||||
&capHeader{_LINUX_CAPABILITY_VERSION_3, 0},
|
||||
&[2]capData{{0, keep[0], keep[0]}, {0, keep[1], keep[1]}},
|
||||
&[2]capData{{keep[0], keep[0], keep[0]}, {keep[1], keep[1], keep[1]}},
|
||||
); err != nil {
|
||||
k.fatalf(msg, "cannot capset: %v", err)
|
||||
}
|
||||
|
||||
for _, c := range keepCaps {
|
||||
if err := k.capAmbientRaise(c); err != nil {
|
||||
k.fatalf(msg, "cannot raise %#x: %v", c, err)
|
||||
}
|
||||
}
|
||||
|
||||
if !param.SeccompDisable {
|
||||
rules := param.SeccompRules
|
||||
if len(rules) == 0 { // non-empty rules slice always overrides presets
|
||||
@@ -474,6 +549,14 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
|
||||
cmd.ExtraFiles = extraFiles
|
||||
cmd.Dir = param.Dir.String()
|
||||
|
||||
if param.InitAsRoot {
|
||||
cmd.SysProcAttr = &SysProcAttr{
|
||||
Cloneflags: CLONE_NEWUSER,
|
||||
UidMappings: []SysProcIDMap{{ContainerID: param.Uid, HostID: 0, Size: 1}},
|
||||
GidMappings: []SysProcIDMap{{ContainerID: param.Gid, HostID: 0, Size: 1}},
|
||||
}
|
||||
}
|
||||
|
||||
msg.Verbosef("starting initial process %s", param.Path)
|
||||
if err := k.start(cmd); err != nil {
|
||||
k.fatalf(msg, "%v", err)
|
||||
|
||||
@@ -332,6 +332,8 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("fatalf", stub.ExpectArgs{"invalid op at index %d", []any{0}}, nil, nil),
|
||||
/* end early */
|
||||
@@ -370,6 +372,8 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("fatalf", stub.ExpectArgs{"invalid op at index %d", []any{0}}, nil, nil),
|
||||
/* end early */
|
||||
@@ -408,6 +412,8 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", stub.UniqueError(61)),
|
||||
call("fatalf", stub.ExpectArgs{"cannot prepare op at index %d: %v", []any{0, stub.UniqueError(61)}}, nil, nil),
|
||||
@@ -447,6 +453,8 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", &os.PathError{Op: "readlink", Path: "/", Err: stub.UniqueError(60)}),
|
||||
call("fatal", stub.ExpectArgs{[]any{"cannot readlink /: unique error 60 injected by the test suite"}}, nil, nil),
|
||||
@@ -486,9 +494,6 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, stub.UniqueError(58)),
|
||||
call("fatalf", stub.ExpectArgs{"cannot mount intermediate root: %v", []any{stub.UniqueError(58)}}, nil, nil),
|
||||
},
|
||||
@@ -526,9 +531,6 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, stub.UniqueError(56)),
|
||||
call("fatalf", stub.ExpectArgs{"cannot enter intermediate host path: %v", []any{stub.UniqueError(56)}}, nil, nil),
|
||||
@@ -567,11 +569,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, stub.UniqueError(54)),
|
||||
call("fatalf", stub.ExpectArgs{"%v", []any{stub.UniqueError(54)}}, nil, nil),
|
||||
},
|
||||
@@ -609,11 +611,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, stub.UniqueError(52)),
|
||||
call("fatalf", stub.ExpectArgs{"cannot bind sysroot: %v", []any{stub.UniqueError(52)}}, nil, nil),
|
||||
@@ -652,11 +654,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, stub.UniqueError(50)),
|
||||
@@ -696,11 +698,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -741,11 +743,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -787,11 +789,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -842,11 +844,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -897,11 +899,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -953,11 +955,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1010,11 +1012,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1069,11 +1071,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1129,11 +1131,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1190,11 +1192,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1252,11 +1254,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1315,11 +1317,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1379,11 +1381,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1444,11 +1446,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1510,11 +1512,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1584,11 +1586,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1622,7 +1624,6 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
||||
@@ -1654,8 +1655,9 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0x200100, 0x200100, 0x200100}, {0, 0, 0}}}, nil, nil),
|
||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, stub.UniqueError(19)),
|
||||
call("fatalf", stub.ExpectArgs{"cannot raise CAP_SYS_ADMIN: %v", []any{stub.UniqueError(19)}}, nil, nil),
|
||||
call("fatalf", stub.ExpectArgs{"cannot raise %#x: %v", []any{uintptr(0x15), stub.UniqueError(19)}}, nil, nil),
|
||||
},
|
||||
}, nil},
|
||||
|
||||
@@ -1691,11 +1693,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1729,7 +1731,6 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
||||
@@ -1761,8 +1762,7 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, stub.UniqueError(17)),
|
||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0x200100, 0x200100, 0x200100}, {0, 0, 0}}}, nil, stub.UniqueError(17)),
|
||||
call("fatalf", stub.ExpectArgs{"cannot capset: %v", []any{stub.UniqueError(17)}}, nil, nil),
|
||||
},
|
||||
}, nil},
|
||||
@@ -1799,11 +1799,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -1837,7 +1837,6 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
||||
@@ -1869,8 +1868,9 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0x200100, 0x200100, 0x200100}, {0, 0, 0}}}, nil, nil),
|
||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, nil),
|
||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
||||
call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{std.FilterPreset(0xf)}}, nil, nil),
|
||||
call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, stub.UniqueError(15)),
|
||||
call("fatalf", stub.ExpectArgs{"cannot load syscall filter: %v", []any{stub.UniqueError(15)}}, nil, nil),
|
||||
@@ -1908,11 +1908,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -2032,11 +2032,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -2132,11 +2132,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -2232,11 +2232,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -2323,11 +2323,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -2418,11 +2418,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(4), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -2520,11 +2520,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -2659,11 +2659,11 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil),
|
||||
call("lastcap", stub.ExpectArgs{}, uintptr(40), nil),
|
||||
call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
/* begin early */
|
||||
call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil),
|
||||
/* end early */
|
||||
call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil),
|
||||
call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil),
|
||||
call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil),
|
||||
@@ -2697,7 +2697,6 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x5)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x6)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x7)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x9)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xa)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0xb)}, nil, nil),
|
||||
@@ -2729,8 +2728,9 @@ func TestInitEntrypoint(t *testing.T) {
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x26)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x27)}, nil, nil),
|
||||
call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x28)}, nil, nil),
|
||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0x200100, 0x200100, 0x200100}, {0, 0, 0}}}, nil, nil),
|
||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x15)}, nil, nil),
|
||||
call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, &[2]capData{{0, 0x200000, 0x200000}, {0, 0, 0}}}, nil, nil),
|
||||
call("capAmbientRaise", stub.ExpectArgs{uintptr(0x8)}, nil, nil),
|
||||
call("verbosef", stub.ExpectArgs{"resolving presets %#x", []any{std.FilterPreset(0xf)}}, nil, nil),
|
||||
call("seccompLoad", stub.ExpectArgs{seccomp.Preset(0xf, 0), seccomp.ExportFlag(0)}, nil, nil),
|
||||
call("verbosef", stub.ExpectArgs{"%d filter rules loaded", []any{73}}, nil, nil),
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/ext"
|
||||
"hakurei.app/fhs"
|
||||
)
|
||||
|
||||
@@ -150,7 +150,7 @@ func (o *MountOverlayOp) early(_ *setupState, k syscallDispatcher) error {
|
||||
if v, err := k.evalSymlinks(o.Upper.String()); err != nil {
|
||||
return err
|
||||
} else {
|
||||
o.upper = check.EscapeOverlayDataSegment(toHost(v))
|
||||
o.upper = toHost(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ func (o *MountOverlayOp) early(_ *setupState, k syscallDispatcher) error {
|
||||
if v, err := k.evalSymlinks(o.Work.String()); err != nil {
|
||||
return err
|
||||
} else {
|
||||
o.work = check.EscapeOverlayDataSegment(toHost(v))
|
||||
o.work = toHost(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,12 +168,39 @@ func (o *MountOverlayOp) early(_ *setupState, k syscallDispatcher) error {
|
||||
if v, err := k.evalSymlinks(a.String()); err != nil {
|
||||
return err
|
||||
} else {
|
||||
o.lower[i] = check.EscapeOverlayDataSegment(toHost(v))
|
||||
o.lower[i] = toHost(v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mountOverlay sets up an overlay mount via [ext.FS].
|
||||
func mountOverlay(target string, options [][2]string) error {
|
||||
fs, err := ext.OpenFS(SourceOverlay, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = fs.SetString("source", SourceOverlay); err != nil {
|
||||
_ = fs.Close()
|
||||
return err
|
||||
}
|
||||
for _, option := range options {
|
||||
if err = fs.SetString(option[0], option[1]); err != nil {
|
||||
_ = fs.Close()
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = fs.SetFlag(OptionOverlayUserxattr); err != nil {
|
||||
_ = fs.Close()
|
||||
return err
|
||||
}
|
||||
if err = fs.Mount(target, 0); err != nil {
|
||||
_ = fs.Close()
|
||||
return err
|
||||
}
|
||||
return fs.Close()
|
||||
}
|
||||
|
||||
func (o *MountOverlayOp) apply(state *setupState, k syscallDispatcher) error {
|
||||
target := o.Target.String()
|
||||
if !o.noPrefix {
|
||||
@@ -194,7 +221,7 @@ func (o *MountOverlayOp) apply(state *setupState, k syscallDispatcher) error {
|
||||
}
|
||||
}
|
||||
|
||||
options := make([]string, 0, 4)
|
||||
options := make([][2]string, 0, 2+len(o.lower))
|
||||
|
||||
if o.upper == zeroString && o.work == zeroString { // readonly
|
||||
if len(o.Lower) < 2 {
|
||||
@@ -205,15 +232,16 @@ func (o *MountOverlayOp) apply(state *setupState, k syscallDispatcher) error {
|
||||
if len(o.Lower) == 0 {
|
||||
return &OverlayArgumentError{OverlayEmptyLower, zeroString}
|
||||
}
|
||||
options = append(options,
|
||||
OptionOverlayUpperdir+"="+o.upper,
|
||||
OptionOverlayWorkdir+"="+o.work)
|
||||
options = append(options, [][2]string{
|
||||
{OptionOverlayUpperdir, o.upper},
|
||||
{OptionOverlayWorkdir, o.work},
|
||||
}...)
|
||||
}
|
||||
for _, lower := range o.lower {
|
||||
options = append(options, [2]string{OptionOverlayLowerdir + "+", lower})
|
||||
}
|
||||
options = append(options,
|
||||
OptionOverlayLowerdir+"="+strings.Join(o.lower, check.SpecialOverlayPath),
|
||||
OptionOverlayUserxattr)
|
||||
|
||||
return k.mount(SourceOverlay, target, FstypeOverlay, 0, strings.Join(options, check.SpecialOverlayOption))
|
||||
return k.mountOverlay(target, options)
|
||||
}
|
||||
|
||||
func (o *MountOverlayOp) late(*setupState, syscallDispatcher) error { return nil }
|
||||
|
||||
@@ -97,13 +97,12 @@ func TestMountOverlayOp(t *testing.T) {
|
||||
call("mkdirAll", stub.ExpectArgs{"/sysroot", os.FileMode(0705)}, nil, nil),
|
||||
call("mkdirTemp", stub.ExpectArgs{"/", "overlay.upper.*"}, "overlay.upper.32768", nil),
|
||||
call("mkdirTemp", stub.ExpectArgs{"/", "overlay.work.*"}, "overlay.work.32768", nil),
|
||||
call("mount", stub.ExpectArgs{"overlay", "/sysroot", "overlay", uintptr(0), "" +
|
||||
"upperdir=overlay.upper.32768," +
|
||||
"workdir=overlay.work.32768," +
|
||||
"lowerdir=" +
|
||||
`/host/var/lib/planterette/base/debian\:f92c9052:` +
|
||||
`/host/var/lib/planterette/app/org.chromium.Chromium@debian\:f92c9052,` +
|
||||
"userxattr"}, nil, nil),
|
||||
call("mountOverlay", stub.ExpectArgs{"/sysroot", [][2]string{
|
||||
{"upperdir", "overlay.upper.32768"},
|
||||
{"workdir", "overlay.work.32768"},
|
||||
{"lowerdir+", `/host/var/lib/planterette/base/debian:f92c9052`},
|
||||
{"lowerdir+", `/host/var/lib/planterette/app/org.chromium.Chromium@debian:f92c9052`},
|
||||
}}, nil, nil),
|
||||
}, nil},
|
||||
|
||||
{"short lower ro", &Params{ParentPerm: 0755}, &MountOverlayOp{
|
||||
@@ -129,11 +128,10 @@ func TestMountOverlayOp(t *testing.T) {
|
||||
call("evalSymlinks", stub.ExpectArgs{"/mnt-root/nix/.ro-store0"}, "/mnt-root/nix/.ro-store0", nil),
|
||||
}, nil, []stub.Call{
|
||||
call("mkdirAll", stub.ExpectArgs{"/nix/store", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"overlay", "/nix/store", "overlay", uintptr(0), "" +
|
||||
"lowerdir=" +
|
||||
"/host/mnt-root/nix/.ro-store:" +
|
||||
"/host/mnt-root/nix/.ro-store0," +
|
||||
"userxattr"}, nil, nil),
|
||||
call("mountOverlay", stub.ExpectArgs{"/nix/store", [][2]string{
|
||||
{"lowerdir+", "/host/mnt-root/nix/.ro-store"},
|
||||
{"lowerdir+", "/host/mnt-root/nix/.ro-store0"},
|
||||
}}, nil, nil),
|
||||
}, nil},
|
||||
|
||||
{"success ro", &Params{ParentPerm: 0755}, &MountOverlayOp{
|
||||
@@ -147,11 +145,10 @@ func TestMountOverlayOp(t *testing.T) {
|
||||
call("evalSymlinks", stub.ExpectArgs{"/mnt-root/nix/.ro-store0"}, "/mnt-root/nix/.ro-store0", nil),
|
||||
}, nil, []stub.Call{
|
||||
call("mkdirAll", stub.ExpectArgs{"/sysroot/nix/store", os.FileMode(0755)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"overlay", "/sysroot/nix/store", "overlay", uintptr(0), "" +
|
||||
"lowerdir=" +
|
||||
"/host/mnt-root/nix/.ro-store:" +
|
||||
"/host/mnt-root/nix/.ro-store0," +
|
||||
"userxattr"}, nil, nil),
|
||||
call("mountOverlay", stub.ExpectArgs{"/sysroot/nix/store", [][2]string{
|
||||
{"lowerdir+", "/host/mnt-root/nix/.ro-store"},
|
||||
{"lowerdir+", "/host/mnt-root/nix/.ro-store0"},
|
||||
}}, nil, nil),
|
||||
}, nil},
|
||||
|
||||
{"nil lower", &Params{ParentPerm: 0700}, &MountOverlayOp{
|
||||
@@ -219,7 +216,11 @@ func TestMountOverlayOp(t *testing.T) {
|
||||
call("evalSymlinks", stub.ExpectArgs{"/mnt-root/nix/.ro-store"}, "/mnt-root/nix/ro-store", nil),
|
||||
}, nil, []stub.Call{
|
||||
call("mkdirAll", stub.ExpectArgs{"/sysroot/nix/store", os.FileMode(0700)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"overlay", "/sysroot/nix/store", "overlay", uintptr(0), "upperdir=/host/mnt-root/nix/.rw-store/.upper,workdir=/host/mnt-root/nix/.rw-store/.work,lowerdir=/host/mnt-root/nix/ro-store,userxattr"}, nil, stub.UniqueError(0)),
|
||||
call("mountOverlay", stub.ExpectArgs{"/sysroot/nix/store", [][2]string{
|
||||
{"upperdir", "/host/mnt-root/nix/.rw-store/.upper"},
|
||||
{"workdir", "/host/mnt-root/nix/.rw-store/.work"},
|
||||
{"lowerdir+", "/host/mnt-root/nix/ro-store"},
|
||||
}}, nil, stub.UniqueError(0)),
|
||||
}, stub.UniqueError(0)},
|
||||
|
||||
{"success single layer", &Params{ParentPerm: 0700}, &MountOverlayOp{
|
||||
@@ -233,11 +234,11 @@ func TestMountOverlayOp(t *testing.T) {
|
||||
call("evalSymlinks", stub.ExpectArgs{"/mnt-root/nix/.ro-store"}, "/mnt-root/nix/ro-store", nil),
|
||||
}, nil, []stub.Call{
|
||||
call("mkdirAll", stub.ExpectArgs{"/sysroot/nix/store", os.FileMode(0700)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"overlay", "/sysroot/nix/store", "overlay", uintptr(0), "" +
|
||||
"upperdir=/host/mnt-root/nix/.rw-store/.upper," +
|
||||
"workdir=/host/mnt-root/nix/.rw-store/.work," +
|
||||
"lowerdir=/host/mnt-root/nix/ro-store," +
|
||||
"userxattr"}, nil, nil),
|
||||
call("mountOverlay", stub.ExpectArgs{"/sysroot/nix/store", [][2]string{
|
||||
{"upperdir", "/host/mnt-root/nix/.rw-store/.upper"},
|
||||
{"workdir", "/host/mnt-root/nix/.rw-store/.work"},
|
||||
{"lowerdir+", "/host/mnt-root/nix/ro-store"},
|
||||
}}, nil, nil),
|
||||
}, nil},
|
||||
|
||||
{"success", &Params{ParentPerm: 0700}, &MountOverlayOp{
|
||||
@@ -261,16 +262,15 @@ func TestMountOverlayOp(t *testing.T) {
|
||||
call("evalSymlinks", stub.ExpectArgs{"/mnt-root/nix/.ro-store3"}, "/mnt-root/nix/ro-store3", nil),
|
||||
}, nil, []stub.Call{
|
||||
call("mkdirAll", stub.ExpectArgs{"/sysroot/nix/store", os.FileMode(0700)}, nil, nil),
|
||||
call("mount", stub.ExpectArgs{"overlay", "/sysroot/nix/store", "overlay", uintptr(0), "" +
|
||||
"upperdir=/host/mnt-root/nix/.rw-store/.upper," +
|
||||
"workdir=/host/mnt-root/nix/.rw-store/.work," +
|
||||
"lowerdir=" +
|
||||
"/host/mnt-root/nix/ro-store:" +
|
||||
"/host/mnt-root/nix/ro-store0:" +
|
||||
"/host/mnt-root/nix/ro-store1:" +
|
||||
"/host/mnt-root/nix/ro-store2:" +
|
||||
"/host/mnt-root/nix/ro-store3," +
|
||||
"userxattr"}, nil, nil),
|
||||
call("mountOverlay", stub.ExpectArgs{"/sysroot/nix/store", [][2]string{
|
||||
{"upperdir", "/host/mnt-root/nix/.rw-store/.upper"},
|
||||
{"workdir", "/host/mnt-root/nix/.rw-store/.work"},
|
||||
{"lowerdir+", "/host/mnt-root/nix/ro-store"},
|
||||
{"lowerdir+", "/host/mnt-root/nix/ro-store0"},
|
||||
{"lowerdir+", "/host/mnt-root/nix/ro-store1"},
|
||||
{"lowerdir+", "/host/mnt-root/nix/ro-store2"},
|
||||
{"lowerdir+", "/host/mnt-root/nix/ro-store3"},
|
||||
}}, nil, nil),
|
||||
}, nil},
|
||||
})
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@ const (
|
||||
// SourceMqueue is used when mounting mqueue.
|
||||
// Note that any source value is allowed when fstype is [FstypeMqueue].
|
||||
SourceMqueue = "mqueue"
|
||||
// SourceBinfmtMisc is used when mounting binfmt_misc.
|
||||
// Note that any source value is allowed when fstype is [SourceBinfmtMisc].
|
||||
SourceBinfmtMisc = "binfmt_misc"
|
||||
// SourceOverlay is used when mounting overlay.
|
||||
// Note that any source value is allowed when fstype is [FstypeOverlay].
|
||||
SourceOverlay = "overlay"
|
||||
@@ -70,6 +73,9 @@ const (
|
||||
// FstypeMqueue represents the mqueue pseudo-filesystem.
|
||||
// This filesystem type is usually mounted on /dev/mqueue.
|
||||
FstypeMqueue = "mqueue"
|
||||
// FstypeBinfmtMisc represents the binfmt_misc pseudo-filesystem.
|
||||
// This filesystem type is usually mounted on /proc/sys/fs/binfmt_misc.
|
||||
FstypeBinfmtMisc = "binfmt_misc"
|
||||
// FstypeOverlay represents the overlay pseudo-filesystem.
|
||||
// This filesystem type can be mounted anywhere in the container filesystem.
|
||||
FstypeOverlay = "overlay"
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/vfs"
|
||||
)
|
||||
|
||||
@@ -50,9 +49,6 @@ func TestToHost(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// InternalToHostOvlEscape exports toHost passed to [check.EscapeOverlayDataSegment].
|
||||
func InternalToHostOvlEscape(s string) string { return check.EscapeOverlayDataSegment(toHost(s)) }
|
||||
|
||||
func TestCreateFile(t *testing.T) {
|
||||
t.Run("nonexistent", func(t *testing.T) {
|
||||
t.Run("mkdir", func(t *testing.T) {
|
||||
|
||||
267
ext/fs.go
Normal file
267
ext/fs.go
Normal file
@@ -0,0 +1,267 @@
|
||||
package ext
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// include/uapi/linux/mount.h
|
||||
|
||||
/*
|
||||
* move_mount() flags.
|
||||
*/
|
||||
const (
|
||||
MOVE_MOUNT_F_SYMLINKS = 1 << iota /* Follow symlinks on from path */
|
||||
MOVE_MOUNT_F_AUTOMOUNTS /* Follow automounts on from path */
|
||||
MOVE_MOUNT_F_EMPTY_PATH /* Empty from path permitted */
|
||||
_
|
||||
MOVE_MOUNT_T_SYMLINKS /* Follow symlinks on to path */
|
||||
MOVE_MOUNT_T_AUTOMOUNTS /* Follow automounts on to path */
|
||||
MOVE_MOUNT_T_EMPTY_PATH /* Empty to path permitted */
|
||||
_
|
||||
MOVE_MOUNT_SET_GROUP /* Set sharing group instead */
|
||||
MOVE_MOUNT_BENEATH /* Mount beneath top mount */
|
||||
)
|
||||
|
||||
/*
|
||||
* fsopen() flags.
|
||||
*/
|
||||
const (
|
||||
FSOPEN_CLOEXEC = 1 << iota
|
||||
)
|
||||
|
||||
/*
|
||||
* fspick() flags.
|
||||
*/
|
||||
const (
|
||||
FSPICK_CLOEXEC = 1 << iota
|
||||
FSPICK_SYMLINK_NOFOLLOW
|
||||
FSPICK_NO_AUTOMOUNT
|
||||
FSPICK_EMPTY_PATH
|
||||
)
|
||||
|
||||
/*
|
||||
* The type of fsconfig() call made.
|
||||
*/
|
||||
const (
|
||||
FSCONFIG_SET_FLAG = iota /* Set parameter, supplying no value */
|
||||
FSCONFIG_SET_STRING /* Set parameter, supplying a string value */
|
||||
FSCONFIG_SET_BINARY /* Set parameter, supplying a binary blob value */
|
||||
FSCONFIG_SET_PATH /* Set parameter, supplying an object by path */
|
||||
FSCONFIG_SET_PATH_EMPTY /* Set parameter, supplying an object by (empty) path */
|
||||
FSCONFIG_SET_FD /* Set parameter, supplying an object by fd */
|
||||
FSCONFIG_CMD_CREATE /* Create new or reuse existing superblock */
|
||||
FSCONFIG_CMD_RECONFIGURE /* Invoke superblock reconfiguration */
|
||||
FSCONFIG_CMD_CREATE_EXCL /* Create new superblock, fail if reusing existing superblock */
|
||||
)
|
||||
|
||||
/*
|
||||
* fsmount() flags.
|
||||
*/
|
||||
const (
|
||||
FSMOUNT_CLOEXEC = 1 << iota
|
||||
)
|
||||
|
||||
/*
|
||||
* Mount attributes.
|
||||
*/
|
||||
const (
|
||||
MOUNT_ATTR_RDONLY = 0x00000001 /* Mount read-only */
|
||||
MOUNT_ATTR_NOSUID = 0x00000002 /* Ignore suid and sgid bits */
|
||||
MOUNT_ATTR_NODEV = 0x00000004 /* Disallow access to device special files */
|
||||
MOUNT_ATTR_NOEXEC = 0x00000008 /* Disallow program execution */
|
||||
MOUNT_ATTR__ATIME = 0x00000070 /* Setting on how atime should be updated */
|
||||
MOUNT_ATTR_RELATIME = 0x00000000 /* - Update atime relative to mtime/ctime. */
|
||||
MOUNT_ATTR_NOATIME = 0x00000010 /* - Do not update access times. */
|
||||
MOUNT_ATTR_STRICTATIME = 0x00000020 /* - Always perform atime updates */
|
||||
MOUNT_ATTR_NODIRATIME = 0x00000080 /* Do not update directory access times */
|
||||
MOUNT_ATTR_IDMAP = 0x00100000 /* Idmap mount to @userns_fd in struct mount_attr. */
|
||||
MOUNT_ATTR_NOSYMFOLLOW = 0x00200000 /* Do not follow symlinks */
|
||||
)
|
||||
|
||||
// FS provides low-level wrappers around the suite of file-descriptor-based
|
||||
// mount facilities in Linux.
|
||||
type FS struct {
|
||||
fd uintptr
|
||||
c runtime.Cleanup
|
||||
}
|
||||
|
||||
// newFS allocates a new [FS] for the specified fd.
|
||||
func newFS(fd uintptr) *FS {
|
||||
fs := FS{fd: fd}
|
||||
fs.c = runtime.AddCleanup(&fs, func(fd uintptr) {
|
||||
_ = syscall.Close(int(fd))
|
||||
}, fd)
|
||||
return &fs
|
||||
}
|
||||
|
||||
// Close closes the underlying filesystem context.
|
||||
func (fs *FS) Close() error {
|
||||
if fs == nil {
|
||||
return syscall.EINVAL
|
||||
}
|
||||
err := syscall.Close(int(fs.fd))
|
||||
fs.c.Stop()
|
||||
return err
|
||||
}
|
||||
|
||||
// OpenFS creates a new filesystem context.
|
||||
func OpenFS(fsname string, flags int) (fs *FS, err error) {
|
||||
var s *byte
|
||||
s, err = syscall.BytePtrFromString(fsname)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fd, _, errno := syscall.Syscall(
|
||||
SYS_FSOPEN,
|
||||
uintptr(unsafe.Pointer(s)),
|
||||
uintptr(flags|FSOPEN_CLOEXEC),
|
||||
0,
|
||||
)
|
||||
if errno != 0 {
|
||||
err = os.NewSyscallError("fsopen", errno)
|
||||
} else {
|
||||
fs = newFS(fd)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PickFS selects filesystem for reconfiguration.
|
||||
func PickFS(dirfd int, pathname string, flags int) (fs *FS, err error) {
|
||||
var s *byte
|
||||
s, err = syscall.BytePtrFromString(pathname)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fd, _, errno := syscall.Syscall(
|
||||
SYS_FSPICK,
|
||||
uintptr(dirfd),
|
||||
uintptr(unsafe.Pointer(s)),
|
||||
uintptr(flags|FSPICK_CLOEXEC),
|
||||
)
|
||||
if errno != 0 {
|
||||
err = os.NewSyscallError("fspick", errno)
|
||||
} else {
|
||||
fs = newFS(fd)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// config configures new or existing filesystem context.
|
||||
func (fs *FS) config(cmd uint, key *byte, value unsafe.Pointer, aux int) (err error) {
|
||||
_, _, errno := syscall.Syscall6(
|
||||
SYS_FSCONFIG,
|
||||
fs.fd,
|
||||
uintptr(cmd),
|
||||
uintptr(unsafe.Pointer(key)),
|
||||
uintptr(value),
|
||||
uintptr(aux),
|
||||
0,
|
||||
)
|
||||
if errno != 0 {
|
||||
err = os.NewSyscallError("fsconfig", errno)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SetFlag sets the flag parameter named by key. ([FSCONFIG_SET_FLAG])
|
||||
func (fs *FS) SetFlag(key string) (err error) {
|
||||
var s *byte
|
||||
s, err = syscall.BytePtrFromString(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return fs.config(FSCONFIG_SET_FLAG, s, nil, 0)
|
||||
}
|
||||
|
||||
// SetString sets the string parameter named by key to the value specified by
|
||||
// value. ([FSCONFIG_SET_STRING])
|
||||
func (fs *FS) SetString(key, value string) (err error) {
|
||||
var s0 *byte
|
||||
s0, err = syscall.BytePtrFromString(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var s1 *byte
|
||||
s1, err = syscall.BytePtrFromString(value)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return fs.config(FSCONFIG_SET_STRING, s0, unsafe.Pointer(s1), 0)
|
||||
}
|
||||
|
||||
// mount instantiates mount object from filesystem context.
|
||||
func (fs *FS) mount(flags, attrFlags int) (fsfd int, err error) {
|
||||
r, _, errno := syscall.Syscall(
|
||||
SYS_FSMOUNT,
|
||||
fs.fd,
|
||||
uintptr(flags|FSMOUNT_CLOEXEC),
|
||||
uintptr(attrFlags),
|
||||
)
|
||||
fsfd = int(r)
|
||||
if errno != 0 {
|
||||
err = os.NewSyscallError("fsmount", errno)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MoveMount moves or attaches mount object to filesystem.
|
||||
func MoveMount(
|
||||
fromDirfd int,
|
||||
fromPathname string,
|
||||
toDirfd int,
|
||||
toPathname string,
|
||||
flags int,
|
||||
) (err error) {
|
||||
var s0 *byte
|
||||
s0, err = syscall.BytePtrFromString(fromPathname)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var s1 *byte
|
||||
s1, err = syscall.BytePtrFromString(toPathname)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, _, errno := syscall.Syscall6(
|
||||
SYS_MOVE_MOUNT,
|
||||
uintptr(fromDirfd),
|
||||
uintptr(unsafe.Pointer(s0)),
|
||||
uintptr(toDirfd),
|
||||
uintptr(unsafe.Pointer(s1)),
|
||||
uintptr(flags),
|
||||
0,
|
||||
)
|
||||
if errno != 0 {
|
||||
err = os.NewSyscallError("move_mount", errno)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Mount attaches the underlying filesystem context to the specified pathname.
|
||||
func (fs *FS) Mount(pathname string, attrFlags int) error {
|
||||
if err := fs.config(FSCONFIG_CMD_CREATE_EXCL, nil, nil, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
fd, err := fs.mount(0, attrFlags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = MoveMount(
|
||||
fd, "",
|
||||
-1, pathname,
|
||||
MOVE_MOUNT_F_EMPTY_PATH,
|
||||
)
|
||||
closeErr := syscall.Close(fd)
|
||||
if err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -42,6 +42,8 @@ var (
|
||||
AbsDevShm = unsafeAbs(DevShm)
|
||||
// AbsProc is [Proc] as [check.Absolute].
|
||||
AbsProc = unsafeAbs(Proc)
|
||||
// AbsProcSys is [ProcSys] as [check.Absolute].
|
||||
AbsProcSys = unsafeAbs(ProcSys)
|
||||
// AbsProcSelfExe is [ProcSelfExe] as [check.Absolute].
|
||||
AbsProcSelfExe = unsafeAbs(ProcSelfExe)
|
||||
// AbsSys is [Sys] as [check.Absolute].
|
||||
|
||||
@@ -64,78 +64,6 @@ func TestFlatten(t *testing.T) {
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C"), nil},
|
||||
|
||||
{"sample cache file", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: 0400, Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
||||
"identifier/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
"identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
"identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: 0400, Path: "checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq", Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}},
|
||||
{Mode: 0400, Path: "checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", Data: []byte{0}},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq", Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe", Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("St9rlE-mGZ5gXwiv_hzQ_B8bZP-UUvSNmf4nHUZzCMOumb6hKnheZSe0dmnuc4Q2"), nil},
|
||||
|
||||
{"sample http get cure", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU": {Mode: 0400, Data: []byte("\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/oM-2pUlk-mOxK1t3aMWZer69UdOQlAXiAgMrpZ1476VoOqpYVP1aGFS9_HYy-D8_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: 0400, Path: "checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU", Data: []byte("\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/oM-2pUlk-mOxK1t3aMWZer69UdOQlAXiAgMrpZ1476VoOqpYVP1aGFS9_HYy-D8_", Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("L_0RFHpr9JUS4Zp14rz2dESSRvfLzpvqsLhR1-YjQt8hYlmEdVl7vI3_-v8UNPKs"), nil},
|
||||
|
||||
{"sample directory step simple", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"check": {Mode: 0400, Data: []byte{0, 0}},
|
||||
|
||||
"lib": {Mode: fs.ModeDir | 0700},
|
||||
"lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
|
||||
"lib/pkgconfig": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0500, Path: "."},
|
||||
|
||||
{Mode: 0400, Path: "check", Data: []byte{0, 0}},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "lib"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "lib/libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "lib/pkgconfig"},
|
||||
}, pkg.MustDecode("qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b"), nil},
|
||||
|
||||
{"sample directory step garbage", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
@@ -151,421 +79,6 @@ func TestFlatten(t *testing.T) {
|
||||
|
||||
{Mode: fs.ModeDir | 0500, Path: "lib/pkgconfig"},
|
||||
}, pkg.MustDecode("CUx-3hSbTWPsbMfDhgalG4Ni_GmR9TnVX8F99tY_P5GtkYvczg9RrF5zO0jX9XYT"), nil},
|
||||
|
||||
{"sample directory", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/check": {Mode: 0400, Data: []byte{0, 0}},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/pkgconfig": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b"},
|
||||
{Mode: 0400, Path: "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/check", Data: []byte{0, 0}},
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/pkgconfig"},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY", Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa", Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("WVpvsVqVKg9Nsh744x57h51AuWUoUR2nnh8Md-EYBQpk6ziyTuUn6PLtF2e0Eu_d"), nil},
|
||||
|
||||
{"sample no assume checksum", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M/check": {Mode: 0400, Data: []byte{}},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
||||
"identifier/_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M"},
|
||||
{Mode: 0400, Path: "checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M/check", Data: []byte{}},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("OC290t23aimNo2Rp2pPwan5GI2KRLRdOwYxXQMD9jw0QROgHnNXWodoWdV0hwu2w"), nil},
|
||||
|
||||
{"sample tar step unpack", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check": {Mode: 0400, Data: []byte{0, 0}},
|
||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0500},
|
||||
"identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0500},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0500, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP"},
|
||||
{Mode: 0400, Path: "checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check", Data: []byte{0, 0}},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig"},
|
||||
|
||||
{Mode: fs.ModeDir | 0500, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY", Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa", Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
|
||||
{Mode: fs.ModeDir | 0500, Path: "work"},
|
||||
}, pkg.MustDecode("cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM"), nil},
|
||||
|
||||
{"sample tar", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check": {Mode: 0400, Data: []byte{0, 0}},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
"checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/work": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM")},
|
||||
"identifier/rg7F1D5hwv6o4xctjD5zDq4i5MD0mArTsUIWfhUbik8xC6Bsyt3mjXXOm3goojTz": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP"},
|
||||
{Mode: 0400, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check", Data: []byte{0, 0}},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY", Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa", Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM/work"},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw", Data: []byte("../checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/rg7F1D5hwv6o4xctjD5zDq4i5MD0mArTsUIWfhUbik8xC6Bsyt3mjXXOm3goojTz", Data: []byte("../checksum/cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("NQTlc466JmSVLIyWklm_u8_g95jEEb98PxJU-kjwxLpfdjwMWJq0G8ze9R4Vo1Vu"), nil},
|
||||
|
||||
{"sample tar expand step unpack", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0500, Path: "."},
|
||||
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
}, pkg.MustDecode("CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN"), nil},
|
||||
|
||||
{"sample tar expand", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN")},
|
||||
"identifier/_v1blm2h-_KA-dVaawdpLas6MjHc6rbhhFS8JWwx8iJxZGUu8EBbRrhr5AaZ9PJL": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN/libedac.so", Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw", Data: []byte("../checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_v1blm2h-_KA-dVaawdpLas6MjHc6rbhhFS8JWwx8iJxZGUu8EBbRrhr5AaZ9PJL", Data: []byte("../checksum/CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("hSoSSgCYTNonX3Q8FjvjD1fBl-E-BQyA6OTXro2OadXqbST4tZ-akGXszdeqphRe"), nil},
|
||||
|
||||
{"testtool", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"check": {Mode: 0400, Data: []byte{0}},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0500, Path: "."},
|
||||
|
||||
{Mode: 0400, Path: "check", Data: []byte{0}},
|
||||
}, pkg.MustDecode("GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"), nil},
|
||||
|
||||
{"sample exec container", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
"identifier/dztPS6jRjiZtCF4_p8AzfnxGp6obkhrgFVsxdodbKWUoAEVtDz3MykepJB4kI_ks": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
||||
{Mode: 0400, Path: "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb", Data: []byte{}},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/dztPS6jRjiZtCF4_p8AzfnxGp6obkhrgFVsxdodbKWUoAEVtDz3MykepJB4kI_ks", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("Q5DluWQCAeohLoiGRImurwFp3vdz9IfQCoj7Fuhh73s4KQPRHpEQEnHTdNHmB8Fx"), nil},
|
||||
|
||||
{"testtool net", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"check": {Mode: 0400, Data: []byte("net")},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0500, Path: "."},
|
||||
|
||||
{Mode: 0400, Path: "check", Data: []byte("net")},
|
||||
}, pkg.MustDecode("a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W"), nil},
|
||||
|
||||
{"sample exec net container", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||
"checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W/check": {Mode: 0400, Data: []byte("net")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/G8qPxD9puvvoOVV7lrT80eyDeIl3G_CCFoKw12c8mCjMdG1zF7NEPkwYpNubClK3": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
||||
{Mode: 0400, Path: "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb", Data: []byte{}},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W"},
|
||||
{Mode: 0400, Path: "checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W/check", Data: []byte("net")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/G8qPxD9puvvoOVV7lrT80eyDeIl3G_CCFoKw12c8mCjMdG1zF7NEPkwYpNubClK3", Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("bPYvvqxpfV7xcC1EptqyKNK1klLJgYHMDkzBcoOyK6j_Aj5hb0mXNPwTwPSK5F6Z"), nil},
|
||||
|
||||
{"sample exec container overlay root", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/RdMA-mubnrHuu3Ky1wWyxauSYCO0ZH_zCPUj3uDHqkfwv5sGcByoF_g5PjlGiClb": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/RdMA-mubnrHuu3Ky1wWyxauSYCO0ZH_zCPUj3uDHqkfwv5sGcByoF_g5PjlGiClb", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("PO2DSSCa4yoSgEYRcCSZfQfwow1yRigL3Ry-hI0RDI4aGuFBha-EfXeSJnG_5_Rl"), nil},
|
||||
|
||||
{"sample exec container overlay work", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/5hlaukCirnXE4W_RSLJFOZN47Z5RiHnacXzdFp_70cLgiJUGR6cSb_HaFftkzi0-": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/5hlaukCirnXE4W_RSLJFOZN47Z5RiHnacXzdFp_70cLgiJUGR6cSb_HaFftkzi0-", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("iaRt6l_Wm2n-h5UsDewZxQkCmjZjyL8r7wv32QT2kyV55-Lx09Dq4gfg9BiwPnKs"), nil},
|
||||
|
||||
{"sample exec container multiple layers", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||
"checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK/check": {Mode: 0400, Data: []byte("layers")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
"identifier/B-kc5iJMx8GtlCua4dz6BiJHnDAOUfPjgpbKq4e-QEn0_CZkSYs3fOA1ve06qMs2": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK")},
|
||||
"identifier/p1t_drXr34i-jZNuxDMLaMOdL6tZvQqhavNafGynGqxOZoXAUTSn7kqNh3Ovv3DT": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
||||
{Mode: 0400, Path: "checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb", Data: []byte{}},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK"},
|
||||
{Mode: 0400, Path: "checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK/check", Data: []byte("layers")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/B-kc5iJMx8GtlCua4dz6BiJHnDAOUfPjgpbKq4e-QEn0_CZkSYs3fOA1ve06qMs2", Data: []byte("../checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/p1t_drXr34i-jZNuxDMLaMOdL6tZvQqhavNafGynGqxOZoXAUTSn7kqNh3Ovv3DT", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("O2YzyR7IUGU5J2CADy0hUZ3A5NkP_Vwzs4UadEdn2oMZZVWRtH0xZGJ3HXiimTnZ"), nil},
|
||||
|
||||
{"sample exec container layer promotion", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/kvJIqZo5DKFOxC2ZQ-8_nPaQzEAz9cIm3p6guO-uLqm-xaiPu7oRkSnsu411jd_U": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
"identifier/xXTIYcXmgJWNLC91c417RRrNM9cjELwEZHpGvf8Fk_GNP5agRJp_SicD0w9aMeLJ": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9"},
|
||||
{Mode: 0400, Path: "checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9/check", Data: []byte{0}},
|
||||
{Mode: fs.ModeDir | 0500, Path: "checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/kvJIqZo5DKFOxC2ZQ-8_nPaQzEAz9cIm3p6guO-uLqm-xaiPu7oRkSnsu411jd_U", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK", Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/xXTIYcXmgJWNLC91c417RRrNM9cjELwEZHpGvf8Fk_GNP5agRJp_SicD0w9aMeLJ", Data: []byte("../checksum/GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "temp"},
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("3EaW6WibLi9gl03_UieiFPaFcPy5p4x3JPxrnLJxGaTI-bh3HU9DK9IMx7c3rrNm"), nil},
|
||||
|
||||
{"sample file short", fstest.MapFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0}},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, []pkg.FlatEntry{
|
||||
{Mode: fs.ModeDir | 0700, Path: "."},
|
||||
{Mode: fs.ModeDir | 0700, Path: "checksum"},
|
||||
{Mode: 0400, Path: "checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX", Data: []byte{0}},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "identifier"},
|
||||
{Mode: fs.ModeSymlink | 0777, Path: "identifier/3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi", Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
||||
|
||||
{Mode: fs.ModeDir | 0700, Path: "work"},
|
||||
}, pkg.MustDecode("iR6H5OIsyOW4EwEgtm9rGzGF6DVtyHLySEtwnFE8bnus9VJcoCbR4JIek7Lw-vwT"), nil},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
@@ -9,8 +9,10 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unique"
|
||||
@@ -94,6 +96,32 @@ func MustPath(pathname string, writable bool, a ...Artifact) ExecPath {
|
||||
return ExecPath{check.MustAbs(pathname), a, writable}
|
||||
}
|
||||
|
||||
var (
|
||||
binfmt map[string]container.BinfmtEntry
|
||||
binfmtMu sync.RWMutex
|
||||
)
|
||||
|
||||
// RegisterArch arranges for [KindExec] and [KindExecNet] to support a new
|
||||
// architecture via a binfmt_misc entry. Each architecture must be registered
|
||||
// at most once.
|
||||
func RegisterArch(arch string, e container.BinfmtEntry) {
|
||||
if arch == "" {
|
||||
panic(UnsupportedArchError(arch))
|
||||
}
|
||||
|
||||
binfmtMu.Lock()
|
||||
defer binfmtMu.Unlock()
|
||||
|
||||
if binfmt == nil {
|
||||
binfmt = make(map[string]container.BinfmtEntry)
|
||||
}
|
||||
|
||||
if _, ok := binfmt[arch]; ok {
|
||||
panic("attempting to register " + strconv.Quote(arch) + " twice")
|
||||
}
|
||||
binfmt[arch] = e
|
||||
}
|
||||
|
||||
const (
|
||||
// ExecTimeoutDefault replaces out of range [NewExec] timeout values.
|
||||
ExecTimeoutDefault = 15 * time.Minute
|
||||
@@ -110,6 +138,8 @@ type execArtifact struct {
|
||||
// Caller-supplied user-facing reporting name, guaranteed to be nonzero
|
||||
// during initialisation.
|
||||
name string
|
||||
// Target architecture.
|
||||
arch string
|
||||
// Caller-supplied inner mount points.
|
||||
paths []ExecPath
|
||||
|
||||
@@ -178,7 +208,7 @@ func (a *execNetArtifact) Cure(f *FContext) error {
|
||||
// container and does not affect curing outcome. Because of this, it is omitted
|
||||
// from parameter data for computing identifier.
|
||||
func NewExec(
|
||||
name string,
|
||||
name, arch string,
|
||||
checksum *Checksum,
|
||||
timeout time.Duration,
|
||||
exclusive bool,
|
||||
@@ -193,13 +223,16 @@ func NewExec(
|
||||
if name == "" {
|
||||
name = "exec-" + filepath.Base(pathname.String())
|
||||
}
|
||||
if arch == "" {
|
||||
arch = runtime.GOARCH
|
||||
}
|
||||
if timeout <= 0 {
|
||||
timeout = ExecTimeoutDefault
|
||||
}
|
||||
if timeout > ExecTimeoutMax {
|
||||
timeout = ExecTimeoutMax
|
||||
}
|
||||
a := execArtifact{name, paths, dir, env, pathname, args, timeout, exclusive}
|
||||
a := execArtifact{name, arch, paths, dir, env, pathname, args, timeout, exclusive}
|
||||
if checksum == nil {
|
||||
return &a
|
||||
}
|
||||
@@ -211,6 +244,7 @@ func (*execArtifact) Kind() Kind { return KindExec }
|
||||
|
||||
// Params writes paths, executable pathname and args.
|
||||
func (a *execArtifact) Params(ctx *IContext) {
|
||||
ctx.WriteString(a.arch)
|
||||
ctx.WriteString(a.name)
|
||||
|
||||
ctx.WriteUint32(uint32(len(a.paths)))
|
||||
@@ -257,11 +291,26 @@ func (a *execArtifact) Params(ctx *IContext) {
|
||||
}
|
||||
}
|
||||
|
||||
// UnsupportedArchError describes an unsupported or invalid architecture.
|
||||
type UnsupportedArchError string
|
||||
|
||||
func (e UnsupportedArchError) Error() string {
|
||||
if e == "" {
|
||||
return "invalid architecture name"
|
||||
}
|
||||
return "unsupported architecture " + string(e)
|
||||
}
|
||||
|
||||
// readExecArtifact interprets IR values and returns the address of execArtifact
|
||||
// or execNetArtifact.
|
||||
func readExecArtifact(r *IRReader, net bool) Artifact {
|
||||
r.DiscardAll()
|
||||
|
||||
arch := r.ReadString()
|
||||
if arch == "" {
|
||||
panic(UnsupportedArchError(arch))
|
||||
}
|
||||
|
||||
name := r.ReadString()
|
||||
|
||||
sz := r.ReadUint32()
|
||||
@@ -327,7 +376,7 @@ func readExecArtifact(r *IRReader, net bool) Artifact {
|
||||
}
|
||||
|
||||
return NewExec(
|
||||
name, checksumP, timeout, exclusive, dir, env, pathname, args, paths...,
|
||||
name, arch, checksumP, timeout, exclusive, dir, env, pathname, args, paths...,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -436,11 +485,23 @@ func (a *execArtifact) makeContainer(
|
||||
if z.HostNet {
|
||||
z.Hostname = "cure-net"
|
||||
}
|
||||
z.Quiet = flags&CSuppressInit != 0
|
||||
z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
|
||||
z.Dir, z.Path, z.Args = a.dir, a.path, a.args
|
||||
z.Env = slices.Concat(a.env, []string{EnvJobs + "=" + strconv.Itoa(jobs)})
|
||||
z.Grow(len(a.paths) + 4)
|
||||
|
||||
if a.arch != runtime.GOARCH {
|
||||
binfmtMu.RLock()
|
||||
e, ok := binfmt[a.arch]
|
||||
binfmtMu.RUnlock()
|
||||
if !ok {
|
||||
return nil, UnsupportedArchError(a.arch)
|
||||
}
|
||||
z.Binfmt = []container.BinfmtEntry{e}
|
||||
z.InitAsRoot = true
|
||||
}
|
||||
|
||||
for i, b := range a.paths {
|
||||
if i == overlayWorkIndex {
|
||||
if err = os.MkdirAll(work.String(), 0700); err != nil {
|
||||
@@ -630,12 +691,6 @@ func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) {
|
||||
_ = stdout.Close()
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err != nil && !errors.As(err, new(*exec.ExitError)) {
|
||||
_ = stdout.Close()
|
||||
_ = stderr.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
brStdout, brStderr := f.cache.getReader(stdout), f.cache.getReader(stderr)
|
||||
stdoutDone, stderrDone := make(chan struct{}), make(chan struct{})
|
||||
@@ -650,6 +705,11 @@ func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) {
|
||||
io.TeeReader(brStderr, status),
|
||||
)
|
||||
defer func() {
|
||||
if err != nil && !errors.As(err, new(*exec.ExitError)) {
|
||||
_ = stdout.Close()
|
||||
_ = stderr.Close()
|
||||
}
|
||||
|
||||
<-stdoutDone
|
||||
<-stderrDone
|
||||
f.cache.putReader(brStdout)
|
||||
|
||||
@@ -1,36 +1,55 @@
|
||||
package pkg_test
|
||||
|
||||
//go:generate env CGO_ENABLED=0 go build -tags testtool -o testdata/testtool ./testdata
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"testing"
|
||||
"unique"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/container"
|
||||
"hakurei.app/hst"
|
||||
"hakurei.app/internal/info"
|
||||
"hakurei.app/internal/pkg"
|
||||
"hakurei.app/internal/stub"
|
||||
|
||||
"hakurei.app/internal/pkg/internal/testtool/expected"
|
||||
)
|
||||
|
||||
// testtoolBin is the container test tool binary made available to the
|
||||
// execArtifact for testing its curing environment.
|
||||
//
|
||||
//go:embed testdata/testtool
|
||||
//go:generate env CGO_ENABLED=0 go build -tags testtool -o internal/testtool ./internal/testtool
|
||||
//go:embed internal/testtool/testtool
|
||||
var testtoolBin []byte
|
||||
|
||||
func init() {
|
||||
pathname, err := filepath.Abs("internal/testtool/testtool")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pkg.RegisterArch("cafe", container.BinfmtEntry{
|
||||
Magic: expected.Magic,
|
||||
Interpreter: check.MustAbs(pathname),
|
||||
})
|
||||
}
|
||||
|
||||
func TestExec(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
wantChecksumOffline := pkg.MustDecode(
|
||||
"GPa4aBakdSJd7Tz7LYj_VJFoojzyZinmVcG3k6M5xI6CZ821J5sXLhLDDuS47gi9",
|
||||
)
|
||||
wantOffline := expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"check": {Mode: 0400, Data: []byte{0}},
|
||||
}
|
||||
wantOfflineEncode := pkg.Encode(wantOffline.hash())
|
||||
|
||||
checkWithCache(t, []cacheTestCase{
|
||||
{"offline", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
@@ -38,7 +57,7 @@ func TestExec(t *testing.T) {
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-offline", nil, 0, false,
|
||||
"exec-offline", "", nil, 0, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -58,10 +77,10 @@ func TestExec(t *testing.T) {
|
||||
},
|
||||
}),
|
||||
pkg.MustPath("/opt", false, testtool),
|
||||
), ignorePathname, wantChecksumOffline, nil},
|
||||
), ignorePathname, wantOffline, nil},
|
||||
|
||||
{"error passthrough", pkg.NewExec(
|
||||
"", nil, 0, true,
|
||||
"", "", nil, 0, true,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -74,7 +93,7 @@ func TestExec(t *testing.T) {
|
||||
return stub.UniqueError(0xcafe)
|
||||
},
|
||||
}),
|
||||
), nil, pkg.Checksum{}, &pkg.DependencyCureError{
|
||||
), nil, nil, &pkg.DependencyCureError{
|
||||
{
|
||||
Ident: unique.Make(pkg.ID(pkg.MustDecode(
|
||||
"Sowo6oZRmG6xVtUaxB6bDWZhVsqAJsIJWUp0OPKlE103cY0lodx7dem8J-qQF0Z1",
|
||||
@@ -84,20 +103,20 @@ func TestExec(t *testing.T) {
|
||||
}},
|
||||
|
||||
{"invalid paths", pkg.NewExec(
|
||||
"", nil, 0, false,
|
||||
"", "", nil, 0, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
[]string{"testtool"},
|
||||
|
||||
pkg.ExecPath{},
|
||||
), nil, pkg.Checksum{}, pkg.ErrInvalidPaths},
|
||||
), nil, nil, pkg.ErrInvalidPaths},
|
||||
})
|
||||
|
||||
// check init failure passthrough
|
||||
var exitError *exec.ExitError
|
||||
if _, _, err := c.Cure(pkg.NewExec(
|
||||
"", nil, 0, false,
|
||||
"", "", nil, 0, false,
|
||||
pkg.AbsWork,
|
||||
nil,
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -108,17 +127,35 @@ func TestExec(t *testing.T) {
|
||||
}
|
||||
|
||||
testtoolDestroy(t, base, c)
|
||||
}, pkg.MustDecode("Q5DluWQCAeohLoiGRImurwFp3vdz9IfQCoj7Fuhh73s4KQPRHpEQEnHTdNHmB8Fx")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/" + wantOfflineEncode: {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantOfflineEncode + "/check": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
"identifier/" + expected.Offline: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"net", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
wantChecksum := pkg.MustDecode(
|
||||
"a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W",
|
||||
)
|
||||
wantNet := expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"check": {Mode: 0400, Data: []byte("net")},
|
||||
}
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-net", &wantChecksum, 0, false,
|
||||
"exec-net", "", new(wantNet.hash()), 0, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -138,18 +175,34 @@ func TestExec(t *testing.T) {
|
||||
},
|
||||
}),
|
||||
pkg.MustPath("/opt", false, testtool),
|
||||
), ignorePathname, wantChecksum, nil},
|
||||
), ignorePathname, wantNet, nil},
|
||||
})
|
||||
|
||||
testtoolDestroy(t, base, c)
|
||||
}, pkg.MustDecode("bPYvvqxpfV7xcC1EptqyKNK1klLJgYHMDkzBcoOyK6j_Aj5hb0mXNPwTwPSK5F6Z")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||
"checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W/check": {Mode: 0400, Data: []byte("net")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/" + expected.Net: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/a1F_i9PVQI4qMcoHgTQkORuyWLkC1GLIxOhDt2JpU1NGAxWc5VJzdlfRK-PYBh3W")},
|
||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"overlay root", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-overlay-root", nil, 0, false,
|
||||
"exec-overlay-root", "", nil, 0, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -163,18 +216,32 @@ func TestExec(t *testing.T) {
|
||||
},
|
||||
}),
|
||||
pkg.MustPath("/opt", false, testtool),
|
||||
), ignorePathname, wantChecksumOffline, nil},
|
||||
), ignorePathname, wantOffline, nil},
|
||||
})
|
||||
|
||||
testtoolDestroy(t, base, c)
|
||||
}, pkg.MustDecode("PO2DSSCa4yoSgEYRcCSZfQfwow1yRigL3Ry-hI0RDI4aGuFBha-EfXeSJnG_5_Rl")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/" + wantOfflineEncode: {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantOfflineEncode + "/check": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/" + expected.OvlRoot: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"overlay work", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-overlay-work", nil, 0, false,
|
||||
"exec-overlay-work", "", nil, 0, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||
check.MustAbs("/work/bin/testtool"),
|
||||
@@ -193,18 +260,32 @@ func TestExec(t *testing.T) {
|
||||
return os.MkdirAll(t.GetWorkDir().String(), 0700)
|
||||
},
|
||||
}), pkg.Path(pkg.AbsWork, false /* ignored */, testtool),
|
||||
), ignorePathname, wantChecksumOffline, nil},
|
||||
), ignorePathname, wantOffline, nil},
|
||||
})
|
||||
|
||||
testtoolDestroy(t, base, c)
|
||||
}, pkg.MustDecode("iaRt6l_Wm2n-h5UsDewZxQkCmjZjyL8r7wv32QT2kyV55-Lx09Dq4gfg9BiwPnKs")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/" + wantOfflineEncode: {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantOfflineEncode + "/check": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/" + expected.Work: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"multiple layers", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-multiple-layers", nil, 0, false,
|
||||
"exec-multiple-layers", "", nil, 0, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -245,18 +326,37 @@ func TestExec(t *testing.T) {
|
||||
},
|
||||
}),
|
||||
pkg.MustPath("/opt", false, testtool),
|
||||
), ignorePathname, wantChecksumOffline, nil},
|
||||
), ignorePathname, wantOffline, nil},
|
||||
})
|
||||
|
||||
testtoolDestroy(t, base, c)
|
||||
}, pkg.MustDecode("O2YzyR7IUGU5J2CADy0hUZ3A5NkP_Vwzs4UadEdn2oMZZVWRtH0xZGJ3HXiimTnZ")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/" + wantOfflineEncode: {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantOfflineEncode + "/check": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb": {Mode: 0400, Data: []byte{}},
|
||||
"checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK/check": {Mode: 0400, Data: []byte("layers")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/_gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/OLBgp1GsljhM2TJ-sbHjaiH9txEUvgdDTAzHv2P24donTt6_529l-9Ua0vFImLlb")},
|
||||
"identifier/B-kc5iJMx8GtlCua4dz6BiJHnDAOUfPjgpbKq4e-QEn0_CZkSYs3fOA1ve06qMs2": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK")},
|
||||
"identifier/" + expected.Layers: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"overlay layer promotion", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
testtool, testtoolDestroy := newTesttool()
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-layer-promotion", nil, 0, true,
|
||||
"exec-layer-promotion", "", nil, 0, true,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -276,11 +376,89 @@ func TestExec(t *testing.T) {
|
||||
},
|
||||
}),
|
||||
pkg.MustPath("/opt", false, testtool),
|
||||
), ignorePathname, wantChecksumOffline, nil},
|
||||
), ignorePathname, wantOffline, nil},
|
||||
})
|
||||
|
||||
testtoolDestroy(t, base, c)
|
||||
}, pkg.MustDecode("3EaW6WibLi9gl03_UieiFPaFcPy5p4x3JPxrnLJxGaTI-bh3HU9DK9IMx7c3rrNm")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/" + wantOfflineEncode: {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantOfflineEncode + "/check": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/kvJIqZo5DKFOxC2ZQ-8_nPaQzEAz9cIm3p6guO-uLqm-xaiPu7oRkSnsu411jd_U": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
"identifier/" + expected.Promote: {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantOfflineEncode)},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"binfmt", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
if info.CanDegrade && os.Getenv("ROSA_SKIP_BINFMT") != "" {
|
||||
t.Skip("binfmt_misc test explicitly skipped")
|
||||
}
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"container", pkg.NewExec(
|
||||
"exec-binfmt", "cafe", nil, 0, true,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1", "HAKUREI_BINFMT=1"},
|
||||
check.MustAbs("/opt/bin/sample"),
|
||||
[]string{"sample"},
|
||||
|
||||
pkg.MustPath("/", true, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
params: []byte("empty directory"),
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return os.MkdirAll(t.GetWorkDir().String(), 0700)
|
||||
},
|
||||
}),
|
||||
pkg.MustPath("/opt", false, overrideIdent{pkg.ID{0xfe, 0xff}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
cure: func(t *pkg.TContext) error {
|
||||
work := t.GetWorkDir()
|
||||
if err := os.MkdirAll(
|
||||
work.Append("bin").String(),
|
||||
0700,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(t.GetWorkDir().Append(
|
||||
"bin",
|
||||
"sample",
|
||||
).String(), []byte(expected.Full), 0500)
|
||||
},
|
||||
}}),
|
||||
), ignorePathname, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"check": {Mode: 0400, Data: []byte("binfmt")},
|
||||
}, nil},
|
||||
})
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/5aevg3YpDxjqQZ-pdvXK7YqgkL5JKqcoStYQxeD96kuYar6K2mRQWMHib6NQRnpV": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/5aevg3YpDxjqQZ-pdvXK7YqgkL5JKqcoStYQxeD96kuYar6K2mRQWMHib6NQRnpV/bin": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/5aevg3YpDxjqQZ-pdvXK7YqgkL5JKqcoStYQxeD96kuYar6K2mRQWMHib6NQRnpV/bin/sample": {Mode: 0500, Data: []byte("\xca\xfe\xba\xbe\xfd\xfd:3")},
|
||||
"checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/UnDo4B5KneEUY5b4vRUk_y9MWgkWuw2N8f8a2XayO686xXur-aZmX2-7n_8tKMe3": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/UnDo4B5KneEUY5b4vRUk_y9MWgkWuw2N8f8a2XayO686xXur-aZmX2-7n_8tKMe3/check": {Mode: 0400, Data: []byte("binfmt")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/6VQTJ1lI5BmVuI1YFYJ8ClO3MRORvTTrcWFDcUU-l5Ga8EofxCxGlSTYN-u8dKj_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/UnDo4B5KneEUY5b4vRUk_y9MWgkWuw2N8f8a2XayO686xXur-aZmX2-7n_8tKMe3")},
|
||||
"identifier/_v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/5aevg3YpDxjqQZ-pdvXK7YqgkL5JKqcoStYQxeD96kuYar6K2mRQWMHib6NQRnpV")},
|
||||
"identifier/vjz1MHPcGBKV7sjcs8jQP3cqxJ1hgPTiQBMCEHP9BGXjGxd-tJmEmXKaStObo5gK": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU")},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package pkg_test
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"testing"
|
||||
|
||||
"hakurei.app/check"
|
||||
@@ -10,18 +11,25 @@ import (
|
||||
func TestFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
want := expectsFile{0}
|
||||
checkWithCache(t, []cacheTestCase{
|
||||
{"file", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
cureMany(t, c, []cureStep{
|
||||
{"short", pkg.NewFile("null", []byte{0}), base.Append(
|
||||
"identifier",
|
||||
"3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi",
|
||||
), pkg.MustDecode(
|
||||
"vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX",
|
||||
), nil},
|
||||
), want, nil},
|
||||
})
|
||||
}, pkg.MustDecode(
|
||||
"iR6H5OIsyOW4EwEgtm9rGzGF6DVtyHLySEtwnFE8bnus9VJcoCbR4JIek7Lw-vwT",
|
||||
)},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/" + pkg.Encode(want.hash()): {Mode: 0400, Data: []byte{0}},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/3376ALA7hIUm2LbzH2fDvRezgzod1eTK_G6XjyOgbM2u-6swvkFaF0BOwSl_juBi": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
9
internal/pkg/internal/testtool/expected/expected.go
Normal file
9
internal/pkg/internal/testtool/expected/expected.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// Package expected contains data shared between test helper and test harness.
|
||||
package expected
|
||||
|
||||
const (
|
||||
// Magic are magic bytes in the binfmt test case.
|
||||
Magic = "\xca\xfe\xba\xbe\xfd\xfd"
|
||||
// Full is the full content of the binfmt test case executable.
|
||||
Full = Magic + ":3"
|
||||
)
|
||||
10
internal/pkg/internal/testtool/expected/sum_amd64.go
Normal file
10
internal/pkg/internal/testtool/expected/sum_amd64.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package expected
|
||||
|
||||
const (
|
||||
Offline = "oe7Uv1u5BwxcuX3HLQzZRg1Q5oetJo6jWiKGMOeqLiqBkaVgyKzvx82N81_IzUAz"
|
||||
OvlRoot = "NacZGXwuRkTvcHaG08a22ujJ8qCWN0RSoFlRSR5FSt0ZcBbJ28FRvkYsHEtX7G8i"
|
||||
Layers = "WBJDrATtX6rIE5yAu8ePX3WmDF0Tt9kFiue0m3cRnyRoVx1my8a67fh3CAW486oP"
|
||||
Net = "CmYtj2sNB3LHtqiDuck_Lz3MjLLIiwyP8N4NDitQ1Icvv__LVP9p8tm-sHeQaKKp"
|
||||
Promote = "TX3eCloaQFkV-SZIH6Jg6E5WKH--rcXY1P0jnZKmLFKWrNqnOzd4G9eIBh6i5ywN"
|
||||
Work = "OuNiLSC68pZhAOr1YQ4WbV1tzASA0nxLEBcK7lO7MqxDY_j8dmP_C612RTuF23Lu"
|
||||
)
|
||||
@@ -14,15 +14,29 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/check"
|
||||
"hakurei.app/fhs"
|
||||
"hakurei.app/vfs"
|
||||
|
||||
"hakurei.app/internal/pkg/internal/testtool/expected"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("testtool: ")
|
||||
|
||||
if os.Getenv("HAKUREI_BINFMT") == "1" {
|
||||
wantArgs := []string{"/interpreter", "/opt/bin/sample"}
|
||||
if !slices.Equal(os.Args, wantArgs) {
|
||||
log.Fatalf("Args: %q, want %q", os.Args, wantArgs)
|
||||
}
|
||||
|
||||
if err := os.WriteFile("check", []byte("binfmt"), 0400); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
environ := slices.DeleteFunc(slices.Clone(os.Environ()), func(s string) bool {
|
||||
return s == "CURE_JOBS="+strconv.Itoa(runtime.NumCPU())
|
||||
})
|
||||
@@ -148,59 +162,40 @@ func main() {
|
||||
}
|
||||
|
||||
const checksumEmptyDir = "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU"
|
||||
ident := "dztPS6jRjiZtCF4_p8AzfnxGp6obkhrgFVsxdodbKWUoAEVtDz3MykepJB4kI_ks"
|
||||
ident := expected.Offline
|
||||
log.Println(m)
|
||||
next := func() { m = m.Next; log.Println(m) }
|
||||
|
||||
if overlayRoot {
|
||||
ident = "RdMA-mubnrHuu3Ky1wWyxauSYCO0ZH_zCPUj3uDHqkfwv5sGcByoF_g5PjlGiClb"
|
||||
ident = expected.OvlRoot
|
||||
|
||||
if m.Root != "/" || m.Target != "/" ||
|
||||
m.Source != "overlay" || m.FsType != "overlay" {
|
||||
log.Fatal("unexpected root mount entry")
|
||||
}
|
||||
var lowerdir string
|
||||
var lowerdir []string
|
||||
for _, o := range strings.Split(m.FsOptstr, ",") {
|
||||
const lowerdirKey = "lowerdir="
|
||||
const lowerdirKey = "lowerdir+="
|
||||
if strings.HasPrefix(o, lowerdirKey) {
|
||||
lowerdir = o[len(lowerdirKey):]
|
||||
lowerdir = append(lowerdir, o[len(lowerdirKey):])
|
||||
}
|
||||
}
|
||||
if !layers {
|
||||
if filepath.Base(lowerdir) != checksumEmptyDir {
|
||||
if len(lowerdir) != 1 || filepath.Base(lowerdir[0]) != checksumEmptyDir {
|
||||
log.Fatal("unexpected artifact checksum")
|
||||
}
|
||||
} else {
|
||||
ident = "p1t_drXr34i-jZNuxDMLaMOdL6tZvQqhavNafGynGqxOZoXAUTSn7kqNh3Ovv3DT"
|
||||
ident = expected.Layers
|
||||
|
||||
lowerdirsEscaped := strings.Split(lowerdir, ":")
|
||||
lowerdirs := lowerdirsEscaped[:0]
|
||||
// ignore the option separator since it does not appear in ident
|
||||
for i, e := range lowerdirsEscaped {
|
||||
if len(e) > 0 &&
|
||||
e[len(e)-1] == check.SpecialOverlayEscape[0] &&
|
||||
(len(e) == 1 || e[len(e)-2] != check.SpecialOverlayEscape[0]) {
|
||||
// ignore escaped pathname separator since it does not
|
||||
// appear in ident
|
||||
|
||||
e = e[:len(e)-1]
|
||||
if len(lowerdirsEscaped) != i {
|
||||
lowerdirsEscaped[i+1] = e + lowerdirsEscaped[i+1]
|
||||
continue
|
||||
}
|
||||
}
|
||||
lowerdirs = append(lowerdirs, e)
|
||||
}
|
||||
|
||||
if len(lowerdirs) != 2 ||
|
||||
filepath.Base(lowerdirs[0]) != "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU" ||
|
||||
filepath.Base(lowerdirs[1]) != "nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK" {
|
||||
log.Fatalf("unexpected lowerdirs %s", strings.Join(lowerdirs, ", "))
|
||||
if len(lowerdir) != 2 ||
|
||||
filepath.Base(lowerdir[0]) != "MGWmEfjut2QE2xPJwTsmUzpff4BN_FEnQ7T0j7gvUCCiugJQNwqt9m151fm9D1yU" ||
|
||||
filepath.Base(lowerdir[1]) != "nY_CUdiaUM1OL4cPr5TS92FCJ3rCRV7Hm5oVTzAvMXwC03_QnTRfQ5PPs7mOU9fK" {
|
||||
log.Fatalf("unexpected lowerdirs %s", strings.Join(lowerdir, ", "))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if hostNet {
|
||||
ident = "G8qPxD9puvvoOVV7lrT80eyDeIl3G_CCFoKw12c8mCjMdG1zF7NEPkwYpNubClK3"
|
||||
ident = expected.Net
|
||||
}
|
||||
|
||||
if m.Root != "/sysroot" || m.Target != "/" {
|
||||
@@ -219,14 +214,14 @@ func main() {
|
||||
}
|
||||
|
||||
if promote {
|
||||
ident = "xXTIYcXmgJWNLC91c417RRrNM9cjELwEZHpGvf8Fk_GNP5agRJp_SicD0w9aMeLJ"
|
||||
ident = expected.Promote
|
||||
}
|
||||
|
||||
next() // testtool artifact
|
||||
|
||||
next()
|
||||
if overlayWork {
|
||||
ident = "5hlaukCirnXE4W_RSLJFOZN47Z5RiHnacXzdFp_70cLgiJUGR6cSb_HaFftkzi0-"
|
||||
ident = expected.Work
|
||||
if m.Root != "/" || m.Target != "/work" ||
|
||||
m.Source != "overlay" || m.FsType != "overlay" {
|
||||
log.Fatal("unexpected work mount entry")
|
||||
@@ -3,6 +3,7 @@ package pkg_test
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/fs"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@@ -38,7 +39,7 @@ func TestIRRoundtrip(t *testing.T) {
|
||||
)},
|
||||
|
||||
{"exec offline", pkg.NewExec(
|
||||
"exec-offline", nil, 0, false,
|
||||
"exec-offline", "", nil, 0, false,
|
||||
pkg.AbsWork,
|
||||
[]string{"HAKUREI_TEST=1"},
|
||||
check.MustAbs("/opt/bin/testtool"),
|
||||
@@ -58,7 +59,7 @@ func TestIRRoundtrip(t *testing.T) {
|
||||
)},
|
||||
|
||||
{"exec net", pkg.NewExec(
|
||||
"exec-net",
|
||||
"exec-net", "",
|
||||
(*pkg.Checksum)(bytes.Repeat([]byte{0xfc}, len(pkg.Checksum{}))),
|
||||
0, false,
|
||||
pkg.AbsWork,
|
||||
@@ -105,9 +106,12 @@ func TestIRRoundtrip(t *testing.T) {
|
||||
if err := <-done; err != nil {
|
||||
t.Fatalf("EncodeAll: error = %v", err)
|
||||
}
|
||||
}, pkg.MustDecode(
|
||||
"E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C",
|
||||
),
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
},
|
||||
}
|
||||
}
|
||||
checkWithCache(t, testCasesCache)
|
||||
|
||||
@@ -3,6 +3,7 @@ package pkg_test
|
||||
import (
|
||||
"crypto/sha512"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
@@ -85,7 +86,12 @@ func TestHTTPGet(t *testing.T) {
|
||||
if _, err := f.Cure(r); !reflect.DeepEqual(err, wantErrNotFound) {
|
||||
t.Fatalf("Cure: error = %#v, want %#v", err, wantErrNotFound)
|
||||
}
|
||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"cure", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
r := newRContext(t, c)
|
||||
@@ -144,6 +150,16 @@ func TestHTTPGet(t *testing.T) {
|
||||
if _, _, err := c.Cure(f); !reflect.DeepEqual(err, wantErrNotFound) {
|
||||
t.Fatalf("Pathname: error = %#v, want %#v", err, wantErrNotFound)
|
||||
}
|
||||
}, pkg.MustDecode("L_0RFHpr9JUS4Zp14rz2dESSRvfLzpvqsLhR1-YjQt8hYlmEdVl7vI3_-v8UNPKs")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU": {Mode: 0400, Data: []byte("\x7f\xe1\x69\xa2\xdd\x63\x96\x26\x83\x79\x61\x8b\xf0\x3f\xd5\x16\x9a\x39\x3a\xdb\xcf\xb1\xbc\x8d\x33\xff\x75\xee\x62\x56\xa9\xf0\x27\xac\x13\x94\x69")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/oM-2pUlk-mOxK1t3aMWZer69UdOQlAXiAgMrpZ1476VoOqpYVP1aGFS9_HYy-D8_": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/fLYGIMHgN1louE-JzITJZJo2SDniPu-IHBXubtvQWFO-hXnDVKNuscV7-zlyr5fU")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -617,6 +617,10 @@ const (
|
||||
// CPromoteVariant allows [pkg.Open] to promote an unextended on-disk cache
|
||||
// to the current extension variant. This is a one-way operation.
|
||||
CPromoteVariant
|
||||
|
||||
// CSuppressInit arranges for verbose output of the container init to be
|
||||
// suppressed regardless of [message.Msg] state.
|
||||
CSuppressInit
|
||||
)
|
||||
|
||||
// toplevel holds [context.WithCancel] over caller-supplied context, where all
|
||||
|
||||
@@ -16,9 +16,11 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
"unique"
|
||||
"unsafe"
|
||||
|
||||
@@ -286,6 +288,99 @@ func TestIdent(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// An expectsKnown describes an expected file or directory.
|
||||
type expectsKnown interface {
|
||||
// hash returns the checksum of the represented data.
|
||||
hash() (checksum pkg.Checksum)
|
||||
}
|
||||
|
||||
// An expectsChecksum is a prepared checksum value.
|
||||
type expectsChecksum pkg.Checksum
|
||||
|
||||
// hash returns e.
|
||||
func (e expectsChecksum) hash() pkg.Checksum { return e }
|
||||
|
||||
// An expectsFile is the contents of a file expected by the test suite.
|
||||
type expectsFile []byte
|
||||
|
||||
// hash computes the checksum of e.
|
||||
func (e expectsFile) hash() (checksum pkg.Checksum) {
|
||||
h := sha512.New384()
|
||||
h.Write(e)
|
||||
h.Sum(checksum[:0])
|
||||
return
|
||||
}
|
||||
|
||||
// An expectsFS describes the state of a filesystem expected by the test suite.
|
||||
type expectsFS fstest.MapFS
|
||||
|
||||
// hash computes the checksum of e.
|
||||
func (e expectsFS) hash() (checksum pkg.Checksum) {
|
||||
if err := pkg.HashFS(&checksum, fstest.MapFS(e), "."); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// expectsFrom generates expectsFS for a filesystem directory.
|
||||
func expectsFrom(pathname string) string {
|
||||
var buf strings.Builder
|
||||
buf.WriteString("expectsFS{\n")
|
||||
if err := filepath.WalkDir(pathname, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var rel string
|
||||
if rel, err = filepath.Rel(pathname, path); err != nil {
|
||||
return err
|
||||
}
|
||||
buf.WriteString("\t" + strconv.Quote(rel) + ": {Mode: ")
|
||||
|
||||
var fi fs.FileInfo
|
||||
if fi, err = d.Info(); err != nil {
|
||||
return err
|
||||
}
|
||||
mode := fi.Mode()
|
||||
|
||||
switch {
|
||||
case mode.IsDir():
|
||||
buf.WriteString("fs.ModeDir | 0" +
|
||||
strconv.FormatInt(int64(mode&^fs.ModeDir), 8))
|
||||
|
||||
case mode&fs.ModeSymlink != 0:
|
||||
buf.WriteString("fs.ModeSymlink | 0" +
|
||||
strconv.FormatInt(int64(mode&^fs.ModeSymlink), 8) +
|
||||
", Data: []byte(")
|
||||
var linkname string
|
||||
if linkname, err = os.Readlink(path); err != nil {
|
||||
return err
|
||||
}
|
||||
buf.WriteString(strconv.Quote(linkname))
|
||||
buf.WriteByte(')')
|
||||
|
||||
case mode.IsRegular():
|
||||
buf.WriteString("0" + strconv.FormatInt(int64(mode), 8))
|
||||
var p []byte
|
||||
if p, err = os.ReadFile(path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(p) > 0 {
|
||||
buf.WriteString(", Data: []byte(")
|
||||
buf.WriteString(strconv.Quote(unsafe.String(unsafe.SliceData(p), len(p))))
|
||||
buf.WriteByte(')')
|
||||
}
|
||||
}
|
||||
buf.WriteString("},\n")
|
||||
return nil
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
buf.WriteString("}")
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// cacheTestCase is a test case passed to checkWithCache where a new instance
|
||||
// of [pkg.Cache] is prepared for the test case, and is validated and removed
|
||||
// on test completion.
|
||||
@@ -294,7 +389,7 @@ type cacheTestCase struct {
|
||||
flags int
|
||||
early func(t *testing.T, base *check.Absolute)
|
||||
f func(t *testing.T, base *check.Absolute, c *pkg.Cache)
|
||||
want pkg.Checksum
|
||||
want expectsFS
|
||||
}
|
||||
|
||||
// checkWithCache runs a slice of cacheTestCase.
|
||||
@@ -328,7 +423,7 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
||||
msg := message.New(log.New(os.Stderr, "cache: ", 0))
|
||||
msg.SwapVerbose(testing.Verbose())
|
||||
|
||||
flags := tc.flags
|
||||
flags := tc.flags | pkg.CSuppressInit
|
||||
|
||||
if info.CanDegrade {
|
||||
if _, err := landlock.GetABI(); err != nil {
|
||||
@@ -381,15 +476,13 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
||||
if err := os.RemoveAll(base.Append("status").String()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := tc.want.hash()
|
||||
|
||||
var checksum pkg.Checksum
|
||||
if err := pkg.HashDir(&checksum, base); err != nil {
|
||||
t.Fatalf("HashDir: error = %v", err)
|
||||
} else if checksum != tc.want {
|
||||
t.Fatalf("HashDir: %v", &pkg.ChecksumMismatchError{
|
||||
Got: checksum,
|
||||
Want: tc.want,
|
||||
})
|
||||
} else if checksum != want {
|
||||
t.Fatal(expectsFrom(base.String()))
|
||||
}
|
||||
|
||||
if err := scrubFunc(); err != nil {
|
||||
@@ -408,10 +501,10 @@ func checkWithCache(t *testing.T, testCases []cacheTestCase) {
|
||||
// validate again to make sure scrub did not condemn anything
|
||||
if err := pkg.HashDir(&checksum, base); err != nil {
|
||||
t.Fatalf("HashDir: error = %v", err)
|
||||
} else if checksum != tc.want {
|
||||
} else if checksum != want {
|
||||
t.Fatalf("(scrubbed) HashDir: %v", &pkg.ChecksumMismatchError{
|
||||
Got: checksum,
|
||||
Want: tc.want,
|
||||
Want: want,
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -425,7 +518,7 @@ type cureStep struct {
|
||||
a pkg.Artifact
|
||||
|
||||
pathname *check.Absolute
|
||||
checksum pkg.Checksum
|
||||
output expectsKnown
|
||||
err error
|
||||
}
|
||||
|
||||
@@ -449,14 +542,16 @@ func cureMany(t *testing.T, c *pkg.Cache, steps []cureStep) {
|
||||
t.Fatalf("Cure: error = %v, want %v", err, step.err)
|
||||
} else if step.pathname != ignorePathname && !pathname.Is(step.pathname) {
|
||||
t.Fatalf("Cure: pathname = %q, want %q", pathname, step.pathname)
|
||||
} else if checksum != makeChecksumH(step.checksum) {
|
||||
if checksum == (unique.Handle[pkg.Checksum]{}) {
|
||||
checksum = unique.Make(pkg.Checksum{})
|
||||
} else if step.output == nil || checksum != makeChecksumH(step.output.hash()) {
|
||||
if pathname != nil {
|
||||
if name, _err := filepath.EvalSymlinks(pathname.String()); _err != nil {
|
||||
t.Fatal(_err)
|
||||
} else {
|
||||
t.Fatal(expectsFrom(name))
|
||||
}
|
||||
} else if checksum != (unique.Handle[pkg.Checksum]{}) {
|
||||
t.Fatalf("Cure: unexpected checksum %s", pkg.Encode(checksum.Value()))
|
||||
}
|
||||
t.Fatalf(
|
||||
"Cure: checksum = %s, want %s",
|
||||
pkg.Encode(checksum.Value()), pkg.Encode(step.checksum),
|
||||
)
|
||||
} else {
|
||||
v := any(err)
|
||||
if err == nil {
|
||||
@@ -517,18 +612,12 @@ func newWantScrubError(base *check.Absolute) *pkg.ScrubError {
|
||||
func TestCache(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const testdata = "" +
|
||||
testdata := expectsFile("" +
|
||||
"\x00\x00\x00\x00" +
|
||||
"\xad\x0b\x00" +
|
||||
"\x04" +
|
||||
"\xfe\xfe\x00\x00" +
|
||||
"\xfe\xca\x00\x00"
|
||||
|
||||
testdataChecksum := func() pkg.Checksum {
|
||||
h := sha512.New384()
|
||||
h.Write([]byte(testdata))
|
||||
return (pkg.Checksum)(h.Sum(nil))
|
||||
}()
|
||||
"\xfe\xca\x00\x00")
|
||||
|
||||
testCases := []cacheTestCase{
|
||||
{"file", pkg.CValidateKnown | pkg.CAssumeChecksum, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
@@ -551,31 +640,31 @@ func TestCache(t *testing.T) {
|
||||
{"initial file", newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
identifier,
|
||||
&testdataChecksum,
|
||||
[]byte(testdata), nil,
|
||||
), wantPathname, testdataChecksum, nil},
|
||||
new(testdata.hash()),
|
||||
testdata, nil,
|
||||
), wantPathname, testdata, nil},
|
||||
|
||||
{"identical content", newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
identifier0,
|
||||
&testdataChecksum,
|
||||
[]byte(testdata), nil,
|
||||
), wantPathname0, testdataChecksum, nil},
|
||||
new(testdata.hash()),
|
||||
testdata, nil,
|
||||
), wantPathname0, testdata, nil},
|
||||
|
||||
{"existing entry", newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
identifier,
|
||||
&testdataChecksum,
|
||||
[]byte(testdata), nil,
|
||||
), wantPathname, testdataChecksum, nil},
|
||||
new(testdata.hash()),
|
||||
testdata, nil,
|
||||
), wantPathname, testdata, nil},
|
||||
|
||||
{"checksum mismatch", newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
pkg.ID{0xff, 0},
|
||||
new(pkg.Checksum),
|
||||
[]byte(testdata), nil,
|
||||
), nil, pkg.Checksum{}, &pkg.ChecksumMismatchError{
|
||||
Got: testdataChecksum,
|
||||
testdata, nil,
|
||||
), nil, nil, &pkg.ChecksumMismatchError{
|
||||
Got: testdata.hash(),
|
||||
}},
|
||||
|
||||
{"store without validation", newStubFile(
|
||||
@@ -586,7 +675,7 @@ func TestCache(t *testing.T) {
|
||||
), base.Append(
|
||||
"identifier",
|
||||
"vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX",
|
||||
), pkg.Checksum{
|
||||
), expectsChecksum{
|
||||
0xbe, 0xc0, 0x21, 0xb4, 0xf3, 0x68,
|
||||
0xe3, 0x06, 0x91, 0x34, 0xe0, 0x12,
|
||||
0xc2, 0xb4, 0x30, 0x70, 0x83, 0xd3,
|
||||
@@ -600,7 +689,7 @@ func TestCache(t *testing.T) {
|
||||
{"incomplete implementation", struct{ pkg.Artifact }{&stubArtifact{
|
||||
kind: pkg.KindExec,
|
||||
params: []byte("artifact overridden to be incomplete"),
|
||||
}}, nil, pkg.Checksum{}, pkg.InvalidArtifactError(pkg.MustDecode(
|
||||
}}, nil, nil, pkg.InvalidArtifactError(pkg.MustDecode(
|
||||
"E__uZ1sLIvb84vzSm5Uezb03RogsiaeTt1nfIVv8TKnnf4LqwtSi-smdHhlkZrUJ",
|
||||
))},
|
||||
|
||||
@@ -609,18 +698,18 @@ func TestCache(t *testing.T) {
|
||||
pkg.ID{0xff, 1},
|
||||
nil,
|
||||
nil, stub.UniqueError(0xcafe),
|
||||
), nil, pkg.Checksum{}, stub.UniqueError(0xcafe)},
|
||||
), nil, nil, stub.UniqueError(0xcafe)},
|
||||
|
||||
{"error caching", newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
pkg.ID{0xff, 1},
|
||||
nil,
|
||||
nil, nil,
|
||||
), nil, pkg.Checksum{}, stub.UniqueError(0xcafe)},
|
||||
), nil, nil, stub.UniqueError(0xcafe)},
|
||||
|
||||
{"cache hit bad type", overrideChecksum{testdataChecksum, overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
|
||||
{"cache hit bad type", overrideChecksum{testdata.hash(), overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
}}}, nil, pkg.Checksum{}, pkg.InvalidFileModeError(
|
||||
}}}, nil, nil, pkg.InvalidFileModeError(
|
||||
0400,
|
||||
)},
|
||||
|
||||
@@ -640,7 +729,7 @@ func TestCache(t *testing.T) {
|
||||
cure: func(f *pkg.FContext) error {
|
||||
panic("attempting to cure impossible artifact")
|
||||
},
|
||||
}, nil, pkg.Checksum{}, &pkg.DependencyCureError{
|
||||
}, nil, nil, &pkg.DependencyCureError{
|
||||
{
|
||||
Ident: unique.Make(pkg.ID{0xff, 3}),
|
||||
Err: struct {
|
||||
@@ -662,18 +751,18 @@ func TestCache(t *testing.T) {
|
||||
cureMany(t, c0, []cureStep{
|
||||
{"cache hit ident", overrideIdent{
|
||||
id: identifier,
|
||||
}, wantPathname, testdataChecksum, nil},
|
||||
}, wantPathname, testdata, nil},
|
||||
|
||||
{"cache miss checksum match", newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
testdataChecksum,
|
||||
testdata.hash(),
|
||||
nil,
|
||||
[]byte(testdata),
|
||||
testdata,
|
||||
nil,
|
||||
), base.Append(
|
||||
"identifier",
|
||||
pkg.Encode(testdataChecksum),
|
||||
), testdataChecksum, nil},
|
||||
pkg.Encode(testdata.hash()),
|
||||
), testdata, nil},
|
||||
})
|
||||
|
||||
// cure after close
|
||||
@@ -686,7 +775,21 @@ func TestCache(t *testing.T) {
|
||||
t.Fatalf("(closed) Cure: error = %v", err)
|
||||
}
|
||||
}
|
||||
}, pkg.MustDecode("St9rlE-mGZ5gXwiv_hzQ_B8bZP-UUvSNmf4nHUZzCMOumb6hKnheZSe0dmnuc4Q2")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: 0400, Data: []byte{0}},
|
||||
"checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: 0400, Data: []byte{0, 0, 0, 0, 0xad, 0xb, 0, 4, 0xfe, 0xfe, 0, 0, 0xfe, 0xca, 0, 0}},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/vsAhtPNo4waRNOASwrQwcIPTqb3SBuJOXw2G4T1mNmVZM-wrQTRllmgXqcIIoRcX")},
|
||||
"identifier/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
"identifier/cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
"identifier/deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/0bSFPu5Tnd-2Jj0Mv6co23PW2t3BmHc7eLFj9TgY3eIBg8zislo7xZYNBqovVLcq")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"directory", pkg.CAssumeChecksum, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
id := pkg.MustDecode(
|
||||
@@ -721,9 +824,16 @@ func TestCache(t *testing.T) {
|
||||
).String(),
|
||||
)
|
||||
}
|
||||
wantChecksum := pkg.MustDecode(
|
||||
"qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b",
|
||||
)
|
||||
want := expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"check": {Mode: 0400, Data: []byte{0, 0}},
|
||||
|
||||
"lib": {Mode: fs.ModeDir | 0700},
|
||||
"lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
|
||||
"lib/pkgconfig": {Mode: fs.ModeDir | 0700},
|
||||
}
|
||||
wantPathname := base.Append(
|
||||
"identifier",
|
||||
pkg.Encode(id),
|
||||
@@ -777,33 +887,33 @@ func TestCache(t *testing.T) {
|
||||
}
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"initial directory", overrideChecksum{wantChecksum, overrideIdent{id, &stubArtifact{
|
||||
{"initial directory", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
cure: makeSample,
|
||||
}}}, wantPathname, wantChecksum, nil},
|
||||
}}}, wantPathname, want, nil},
|
||||
|
||||
{"identical identifier", overrideChecksum{wantChecksum, overrideIdent{id, &stubArtifact{
|
||||
{"identical identifier", overrideChecksum{want.hash(), overrideIdent{id, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
}}}, wantPathname, wantChecksum, nil},
|
||||
}}}, wantPathname, want, nil},
|
||||
|
||||
{"identical checksum", overrideIdent{id0, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
cure: makeSample,
|
||||
}}, wantPathname0, wantChecksum, nil},
|
||||
}}, wantPathname0, want, nil},
|
||||
|
||||
{"cure fault", overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xcafe))
|
||||
},
|
||||
}}, nil, pkg.Checksum{}, stub.UniqueError(0xcafe)},
|
||||
}}, nil, nil, stub.UniqueError(0xcafe)},
|
||||
|
||||
{"checksum mismatch", overrideChecksum{pkg.Checksum{}, overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return makeGarbage(t.GetWorkDir(), nil)
|
||||
},
|
||||
}}}, nil, pkg.Checksum{}, &pkg.ChecksumMismatchError{
|
||||
}}}, nil, nil, &pkg.ChecksumMismatchError{
|
||||
Got: pkg.MustDecode(
|
||||
"CUx-3hSbTWPsbMfDhgalG4Ni_GmR9TnVX8F99tY_P5GtkYvczg9RrF5zO0jX9XYT",
|
||||
),
|
||||
@@ -812,27 +922,27 @@ func TestCache(t *testing.T) {
|
||||
{"cache hit bad type", newStubFile(
|
||||
pkg.KindHTTPGet,
|
||||
pkg.ID{0xff, 2},
|
||||
&wantChecksum,
|
||||
[]byte(testdata), nil,
|
||||
), nil, pkg.Checksum{}, pkg.InvalidFileModeError(
|
||||
new(want.hash()),
|
||||
testdata, nil,
|
||||
), nil, nil, pkg.InvalidFileModeError(
|
||||
fs.ModeDir | 0500,
|
||||
)},
|
||||
|
||||
{"openFile directory", overrideIdent{pkg.ID{0xff, 3}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
cure: func(t *pkg.TContext) error {
|
||||
r, err := t.Open(overrideChecksumFile{checksum: wantChecksum})
|
||||
r, err := t.Open(overrideChecksumFile{checksum: want.hash()})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = io.ReadAll(r)
|
||||
return err
|
||||
},
|
||||
}}, nil, pkg.Checksum{}, &os.PathError{
|
||||
}}, nil, nil, &os.PathError{
|
||||
Op: "read",
|
||||
Path: base.Append(
|
||||
"checksum",
|
||||
pkg.Encode(wantChecksum),
|
||||
pkg.Encode(want.hash()),
|
||||
).String(),
|
||||
Err: syscall.EISDIR,
|
||||
}},
|
||||
@@ -842,14 +952,14 @@ func TestCache(t *testing.T) {
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return nil
|
||||
},
|
||||
}}, nil, pkg.Checksum{}, pkg.NoOutputError{}},
|
||||
}}, nil, nil, pkg.NoOutputError{}},
|
||||
|
||||
{"file output", overrideIdent{pkg.ID{0xff, 5}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return os.WriteFile(t.GetWorkDir().String(), []byte{0}, 0400)
|
||||
},
|
||||
}}, nil, pkg.Checksum{}, errors.New("non-file artifact produced regular file")},
|
||||
}}, nil, nil, errors.New("non-file artifact produced regular file")},
|
||||
|
||||
{"symlink output", overrideIdent{pkg.ID{0xff, 6}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
@@ -859,11 +969,26 @@ func TestCache(t *testing.T) {
|
||||
t.GetWorkDir().String(),
|
||||
)
|
||||
},
|
||||
}}, nil, pkg.Checksum{}, pkg.InvalidFileModeError(
|
||||
}}, nil, nil, pkg.InvalidFileModeError(
|
||||
fs.ModeSymlink | 0777,
|
||||
)},
|
||||
})
|
||||
}, pkg.MustDecode("WVpvsVqVKg9Nsh744x57h51AuWUoUR2nnh8Md-EYBQpk6ziyTuUn6PLtF2e0Eu_d")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/check": {Mode: 0400, Data: []byte{0, 0}},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/pkgconfig": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/qRN6in76LndiiOZJheHkwyW8UT1N5-f-bXvHfDvwrMw2fSkOoZdh8pWE1qhLk65b")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"pending", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
wantErr := stub.UniqueError(0xcafe)
|
||||
@@ -899,7 +1024,7 @@ func TestCache(t *testing.T) {
|
||||
pkg.ID{0xff, 1},
|
||||
nil,
|
||||
nil, stub.UniqueError(0xbad),
|
||||
), nil, pkg.Checksum{}, stub.UniqueError(0xbad)},
|
||||
), nil, nil, stub.UniqueError(0xbad)},
|
||||
|
||||
{"file output", overrideIdent{pkg.ID{0xff, 2}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
@@ -910,7 +1035,7 @@ func TestCache(t *testing.T) {
|
||||
0400,
|
||||
)
|
||||
},
|
||||
}}, nil, pkg.Checksum{}, errors.New(
|
||||
}}, nil, nil, errors.New(
|
||||
"non-file artifact produced regular file",
|
||||
)},
|
||||
})
|
||||
@@ -932,7 +1057,12 @@ func TestCache(t *testing.T) {
|
||||
for c.Done(unique.Make(pkg.ID{0xff})) != nil {
|
||||
}
|
||||
<-wCureDone
|
||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"cancel abort block", pkg.CValidateKnown, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
var wg sync.WaitGroup
|
||||
@@ -985,7 +1115,12 @@ func TestCache(t *testing.T) {
|
||||
|
||||
c.Close()
|
||||
c.Abort()
|
||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"no assume checksum", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
makeGarbage := func(work *check.Absolute, wantErr error) error {
|
||||
@@ -1002,10 +1137,12 @@ func TestCache(t *testing.T) {
|
||||
return wantErr
|
||||
}
|
||||
|
||||
wantChecksum := pkg.MustDecode("Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")
|
||||
want := expectsChecksum(pkg.MustDecode(
|
||||
"Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M",
|
||||
))
|
||||
|
||||
cureMany(t, c, []cureStep{
|
||||
{"create", overrideChecksum{wantChecksum, overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{
|
||||
{"create", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xff, 0}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return makeGarbage(t.GetWorkDir(), nil)
|
||||
@@ -1013,16 +1150,16 @@ func TestCache(t *testing.T) {
|
||||
}}}, base.Append(
|
||||
"identifier",
|
||||
pkg.Encode(pkg.ID{0xff, 0}),
|
||||
), wantChecksum, nil},
|
||||
), want, nil},
|
||||
|
||||
{"reject", overrideChecksum{wantChecksum, overrideIdent{pkg.ID{0xfe, 1}, &stubArtifact{
|
||||
{"reject", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xfe, 1}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return makeGarbage(t.GetWorkDir(), stub.UniqueError(0xbad))
|
||||
},
|
||||
}}}, nil, pkg.Checksum{}, stub.UniqueError(0xbad)},
|
||||
}}}, nil, nil, stub.UniqueError(0xbad)},
|
||||
|
||||
{"match", overrideChecksum{wantChecksum, overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
|
||||
{"match", overrideChecksum{want.hash(), overrideIdent{pkg.ID{0xff, 1}, &stubArtifact{
|
||||
kind: pkg.KindTar,
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return makeGarbage(t.GetWorkDir(), nil)
|
||||
@@ -1030,9 +1167,21 @@ func TestCache(t *testing.T) {
|
||||
}}}, base.Append(
|
||||
"identifier",
|
||||
pkg.Encode(pkg.ID{0xff, 1}),
|
||||
), wantChecksum, nil},
|
||||
), want, nil},
|
||||
})
|
||||
}, pkg.MustDecode("OC290t23aimNo2Rp2pPwan5GI2KRLRdOwYxXQMD9jw0QROgHnNXWodoWdV0hwu2w")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M/check": {Mode: 0400, Data: []byte{}},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
||||
"identifier/_wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/Aubi5EG4_Y8DhL9bQ3Q4HFBhLRF7X5gt9D3CNCQfT-TeBtlRXc7Zi_JYZEMoCC7M")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"scrub", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
cureMany(t, c, []cureStep{
|
||||
@@ -1044,7 +1193,7 @@ func TestCache(t *testing.T) {
|
||||
), base.Append(
|
||||
"identifier",
|
||||
pkg.Encode(pkg.Checksum{0xfe, 0}),
|
||||
), pkg.Checksum{0xff, 0}, nil},
|
||||
), expectsChecksum{0xff, 0}, nil},
|
||||
})
|
||||
|
||||
for _, p := range [][]string{
|
||||
@@ -1077,7 +1226,12 @@ func TestCache(t *testing.T) {
|
||||
if err := c.Scrub(1 << 6); !reflect.DeepEqual(err, wantErr) {
|
||||
t.Fatalf("Scrub: error =\n%s\nwant\n%s", err, wantErr)
|
||||
}
|
||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
}
|
||||
checkWithCache(t, testCases)
|
||||
}
|
||||
@@ -1135,6 +1289,11 @@ func TestErrors(t *testing.T) {
|
||||
{"UnsupportedVariantError", pkg.UnsupportedVariantError(
|
||||
"rosa",
|
||||
), `unsupported variant "rosa"`},
|
||||
|
||||
{"UnsupportedArchError zero", pkg.UnsupportedArchError(""),
|
||||
"invalid architecture name"},
|
||||
{"UnsupportedArchError", pkg.UnsupportedArchError("riscv64"),
|
||||
"unsupported architecture riscv64"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@@ -1351,7 +1510,12 @@ func TestDependencyCureErrorEarly(t *testing.T) {
|
||||
if !errors.Is(err, stub.UniqueError(0xcafe)) {
|
||||
t.Fatalf("Cure: error = %v", err)
|
||||
}
|
||||
}, pkg.MustDecode("E4vEZKhCcL2gPZ2Tt59FS3lDng-d_2SKa2i5G_RbDfwGn6EemptFaGLPUDiOa94C")},
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,31 @@ import (
|
||||
func TestTar(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
want := expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check": {Mode: 0400, Data: []byte{0, 0}},
|
||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0500},
|
||||
"identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0500},
|
||||
}
|
||||
wantEncode := pkg.Encode(want.hash())
|
||||
|
||||
wantExpand := expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
}
|
||||
wantExpandEncode := pkg.Encode(wantExpand.hash())
|
||||
|
||||
checkWithCache(t, []cacheTestCase{
|
||||
{"http", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
checkTarHTTP(t, base, c, fstest.MapFS{
|
||||
@@ -37,10 +62,30 @@ func TestTar(t *testing.T) {
|
||||
"identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}, pkg.MustDecode(
|
||||
"cTw0h3AmYe7XudSoyEMByduYXqGi-N5ZkTZ0t9K5elsu3i_jNIVF5T08KR1roBFM",
|
||||
))
|
||||
}, pkg.MustDecode("NQTlc466JmSVLIyWklm_u8_g95jEEb98PxJU-kjwxLpfdjwMWJq0G8ze9R4Vo1Vu")},
|
||||
}, want)
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/" + wantEncode: {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantEncode + "/checksum": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantEncode + "/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantEncode + "/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/check": {Mode: 0400, Data: []byte{0, 0}},
|
||||
"checksum/" + wantEncode + "/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantEncode + "/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
"checksum/" + wantEncode + "/checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP/lib/pkgconfig": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantEncode + "/identifier": {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantEncode + "/identifier/HnySzeLQvSBZuTUcvfmLEX_OmH4yJWWH788NxuLuv7kVn8_uPM6Ks4rqFWM2NZJY": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
"checksum/" + wantEncode + "/identifier/Zx5ZG9BAwegNT3zQwCySuI2ktCXxNgxirkGLFjW4FW06PtojYVaCdtEw8yuntPLa": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/1TL00Qb8dcqayX7wTO8WNaraHvY6b-KCsctLDTrb64QBCmxj_-byK1HdIUwMaFEP")},
|
||||
"checksum/" + wantEncode + "/work": {Mode: fs.ModeDir | 0500},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)},
|
||||
"identifier/rg7F1D5hwv6o4xctjD5zDq4i5MD0mArTsUIWfhUbik8xC6Bsyt3mjXXOm3goojTz": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantEncode)},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
|
||||
{"http expand", 0, nil, func(t *testing.T, base *check.Absolute, c *pkg.Cache) {
|
||||
checkTarHTTP(t, base, c, fstest.MapFS{
|
||||
@@ -48,10 +93,21 @@ func TestTar(t *testing.T) {
|
||||
|
||||
"lib": {Mode: fs.ModeDir | 0700},
|
||||
"lib/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
}, pkg.MustDecode(
|
||||
"CH3AiUrCCcVOjOYLaMKKK1Da78989JtfHeIsxMzWOQFiN4mrCLDYpoDxLWqJWCUN",
|
||||
))
|
||||
}, pkg.MustDecode("hSoSSgCYTNonX3Q8FjvjD1fBl-E-BQyA6OTXro2OadXqbST4tZ-akGXszdeqphRe")},
|
||||
}, wantExpand)
|
||||
}, expectsFS{
|
||||
".": {Mode: fs.ModeDir | 0700},
|
||||
|
||||
"checksum": {Mode: fs.ModeDir | 0700},
|
||||
"checksum/" + wantExpandEncode: {Mode: fs.ModeDir | 0500},
|
||||
"checksum/" + wantExpandEncode + "/libedac.so": {Mode: fs.ModeSymlink | 0777, Data: []byte("/proc/nonexistent/libedac.so")},
|
||||
|
||||
"identifier": {Mode: fs.ModeDir | 0700},
|
||||
"identifier/W5S65DEhawz_WKaok5NjUKLmnD9dNl5RPauNJjcOVcB3VM4eGhSaLGmXbL8vZpiw": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)},
|
||||
"identifier/_v1blm2h-_KA-dVaawdpLas6MjHc6rbhhFS8JWwx8iJxZGUu8EBbRrhr5AaZ9PJL": {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantExpandEncode)},
|
||||
|
||||
"temp": {Mode: fs.ModeDir | 0700},
|
||||
"work": {Mode: fs.ModeDir | 0700},
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -60,7 +116,7 @@ func checkTarHTTP(
|
||||
base *check.Absolute,
|
||||
c *pkg.Cache,
|
||||
testdataFsys fs.FS,
|
||||
wantChecksum pkg.Checksum,
|
||||
want expectsKnown,
|
||||
) {
|
||||
var testdata string
|
||||
{
|
||||
@@ -194,24 +250,24 @@ func checkTarHTTP(
|
||||
{"file", a, base.Append(
|
||||
"identifier",
|
||||
pkg.Encode(wantIdent),
|
||||
), wantChecksum, nil},
|
||||
), want, nil},
|
||||
|
||||
{"directory", pkg.NewTar(
|
||||
&tarDir,
|
||||
pkg.TarGzip,
|
||||
), ignorePathname, wantChecksum, nil},
|
||||
), ignorePathname, want, nil},
|
||||
|
||||
{"multiple entries", pkg.NewTar(
|
||||
&tarDirMulti,
|
||||
pkg.TarGzip,
|
||||
), nil, pkg.Checksum{}, errors.New(
|
||||
), nil, nil, errors.New(
|
||||
"input directory does not contain a single regular file",
|
||||
)},
|
||||
|
||||
{"bad type", pkg.NewTar(
|
||||
&tarDirType,
|
||||
pkg.TarGzip,
|
||||
), nil, pkg.Checksum{}, errors.New(
|
||||
), nil, nil, errors.New(
|
||||
"input directory does not contain a single regular file",
|
||||
)},
|
||||
|
||||
@@ -221,6 +277,6 @@ func checkTarHTTP(
|
||||
cure: func(t *pkg.TContext) error {
|
||||
return stub.UniqueError(0xcafe)
|
||||
},
|
||||
}, pkg.TarGzip), nil, pkg.Checksum{}, stub.UniqueError(0xcafe)},
|
||||
}, pkg.TarGzip), nil, nil, stub.UniqueError(0xcafe)},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
@@ -70,11 +71,21 @@ const (
|
||||
Gzip
|
||||
Hakurei
|
||||
HakureiDist
|
||||
Hwdata
|
||||
IPTables
|
||||
Kmod
|
||||
LIT
|
||||
LibX11
|
||||
LibXau
|
||||
LibXext
|
||||
LibXrandr
|
||||
LibXrender
|
||||
LibXxf86vm
|
||||
Libarchive
|
||||
Libbsd
|
||||
Libcap
|
||||
Libconfig
|
||||
LibdisplayInfo
|
||||
Libdrm
|
||||
Libev
|
||||
Libexpat
|
||||
@@ -84,16 +95,19 @@ const (
|
||||
Libiconv
|
||||
Libmd
|
||||
Libmnl
|
||||
Libpciaccess
|
||||
Libnftnl
|
||||
Libpciaccess
|
||||
Libpng
|
||||
Libpsl
|
||||
Libseccomp
|
||||
Libtasn1
|
||||
Libtool
|
||||
Libucontext
|
||||
Libunistring
|
||||
Libxshmfence
|
||||
Libxml2
|
||||
Libxslt
|
||||
Libxtrans
|
||||
M4
|
||||
MPC
|
||||
MPFR
|
||||
@@ -136,6 +150,7 @@ const (
|
||||
PythonPluggy
|
||||
PythonPyTest
|
||||
PythonPyYAML
|
||||
PythonPycparser
|
||||
PythonPygments
|
||||
PythonSetuptools
|
||||
PythonSetuptoolsSCM
|
||||
@@ -148,6 +163,7 @@ const (
|
||||
Rsync
|
||||
Sed
|
||||
SPIRVHeaders
|
||||
SPIRVLLVMTranslator
|
||||
SPIRVTools
|
||||
SquashfsTools
|
||||
Strace
|
||||
@@ -162,16 +178,31 @@ const (
|
||||
WaylandProtocols
|
||||
XCB
|
||||
XCBProto
|
||||
XCBUtilKeysyms
|
||||
XDGDBusProxy
|
||||
XZ
|
||||
Xproto
|
||||
XorgProto
|
||||
Zlib
|
||||
Zstd
|
||||
|
||||
// PresetUnexportedStart is the first unexported preset.
|
||||
PresetUnexportedStart
|
||||
|
||||
buildcatrust = iota - 1
|
||||
stage0Dist = iota - 1
|
||||
llvmSource
|
||||
// earlyCompilerRT is an early, standalone compiler-rt installation for the
|
||||
// standalone runtimes build.
|
||||
//
|
||||
// earlyCompilerRT must only be loaded by [LLVM].
|
||||
earlyCompilerRT
|
||||
// earlyRuntimes is an early, standalone installation of LLVM runtimes to
|
||||
// work around the cmake build system leaking the system LLVM installation
|
||||
// when invoking the newly built toolchain.
|
||||
//
|
||||
// earlyRuntimes must only be loaded by [LLVM].
|
||||
earlyRuntimes
|
||||
|
||||
buildcatrust
|
||||
utilMacros
|
||||
|
||||
// Musl is a standalone libc that does not depend on the toolchain.
|
||||
@@ -323,6 +354,9 @@ var (
|
||||
// artifactsOnce is for lazy initialisation of artifacts.
|
||||
artifactsOnce [_toolchainEnd][len(artifactsM)]sync.Once
|
||||
|
||||
// arch is the target architecture.
|
||||
arch = runtime.GOARCH
|
||||
|
||||
// presetOpts globally modifies behaviour of presets.
|
||||
presetOpts int
|
||||
)
|
||||
@@ -334,6 +368,9 @@ const (
|
||||
OptLLVMNoLTO
|
||||
)
|
||||
|
||||
// Arch returns the target architecture.
|
||||
func Arch() string { return arch }
|
||||
|
||||
// Flags returns the current preset flags
|
||||
func Flags() int { return presetOpts }
|
||||
|
||||
@@ -343,7 +380,12 @@ func zero[T any](p *T) { var v T; *p = v }
|
||||
// DropCaches arranges for all cached [pkg.Artifact] to be freed some time after
|
||||
// it returns. Must not be used concurrently with any other function from this
|
||||
// package.
|
||||
func DropCaches(flags int) {
|
||||
func DropCaches(targetArch string, flags int) {
|
||||
if targetArch == "" {
|
||||
targetArch = runtime.GOARCH
|
||||
}
|
||||
|
||||
arch = targetArch
|
||||
presetOpts = flags
|
||||
zero(&artifacts)
|
||||
zero(&artifactsOnce)
|
||||
|
||||
@@ -20,8 +20,8 @@ func TestLoad(t *testing.T) {
|
||||
}
|
||||
|
||||
func BenchmarkAll(b *testing.B) {
|
||||
flags := rosa.Flags()
|
||||
b.Cleanup(func() { rosa.DropCaches(flags) })
|
||||
arch, flags := rosa.Arch(), rosa.Flags()
|
||||
b.Cleanup(func() { rosa.DropCaches(arch, flags) })
|
||||
|
||||
for b.Loop() {
|
||||
for i := range rosa.PresetEnd {
|
||||
@@ -29,7 +29,7 @@ func BenchmarkAll(b *testing.B) {
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
rosa.DropCaches(0)
|
||||
rosa.DropCaches("", 0)
|
||||
b.StartTimer()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"hakurei.app/fhs"
|
||||
@@ -88,7 +87,7 @@ func (a busyboxBin) Cure(t *pkg.TContext) (err error) {
|
||||
// the https://busybox.net/downloads/binaries/ binary release.
|
||||
func newBusyboxBin() pkg.Artifact {
|
||||
var version, url, checksum string
|
||||
switch runtime.GOARCH {
|
||||
switch arch {
|
||||
case "amd64":
|
||||
version = "1.35.0"
|
||||
url = "https://busybox.net/downloads/binaries/" +
|
||||
@@ -101,11 +100,11 @@ func newBusyboxBin() pkg.Artifact {
|
||||
checksum = "npJjBO7iwhjW6Kx2aXeSxf8kXhVgTCDChOZTTsI8ZfFfa3tbsklxRiidZQdrVERg"
|
||||
|
||||
default:
|
||||
panic("unsupported target " + runtime.GOARCH)
|
||||
panic("unsupported target " + arch)
|
||||
}
|
||||
|
||||
return pkg.NewExec(
|
||||
"busybox-bin-"+version, nil, pkg.ExecTimeoutMax, false,
|
||||
"busybox-bin-"+version, arch, nil, pkg.ExecTimeoutMax, false,
|
||||
fhs.AbsRoot, []string{
|
||||
"PATH=/system/bin",
|
||||
},
|
||||
|
||||
@@ -122,6 +122,8 @@ type CMakeHelper struct {
|
||||
// Path elements joined with source.
|
||||
Append []string
|
||||
|
||||
// Value of CMAKE_BUILD_TYPE. The zero value is equivalent to "Release".
|
||||
BuildType string
|
||||
// CMake CACHE entries.
|
||||
Cache []KV
|
||||
// Runs after install.
|
||||
@@ -164,14 +166,7 @@ func (*CMakeHelper) wantsDir() string { return "/cure/" }
|
||||
// script generates the cure script.
|
||||
func (attr *CMakeHelper) script(name string) string {
|
||||
if attr == nil {
|
||||
attr = &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
},
|
||||
}
|
||||
}
|
||||
if len(attr.Cache) == 0 {
|
||||
panic("CACHE must be non-empty")
|
||||
attr = new(CMakeHelper)
|
||||
}
|
||||
|
||||
generate := "Ninja"
|
||||
@@ -189,6 +184,13 @@ func (attr *CMakeHelper) script(name string) string {
|
||||
script += "\n" + test
|
||||
}
|
||||
|
||||
cache := make([]KV, 1, 1+len(attr.Cache))
|
||||
cache[0] = KV{"CMAKE_BUILD_TYPE", "Release"}
|
||||
if attr.BuildType != "" {
|
||||
cache[0][1] = attr.BuildType
|
||||
}
|
||||
cache = append(cache, attr.Cache...)
|
||||
|
||||
return `
|
||||
cmake -G ` + generate + ` \
|
||||
-DCMAKE_C_COMPILER_TARGET="${ROSA_TRIPLE}" \
|
||||
@@ -196,7 +198,7 @@ cmake -G ` + generate + ` \
|
||||
-DCMAKE_ASM_COMPILER_TARGET="${ROSA_TRIPLE}" \
|
||||
-DCMAKE_INSTALL_LIBDIR=lib \
|
||||
` + strings.Join(slices.Collect(func(yield func(string) bool) {
|
||||
for _, v := range attr.Cache {
|
||||
for _, v := range cache {
|
||||
if !yield("-D" + v[0] + "=" + v[1]) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -55,6 +55,9 @@ disable_test t9300-fast-import
|
||||
disable_test t0211-trace2-perf
|
||||
disable_test t1517-outside-repo
|
||||
disable_test t2200-add-update
|
||||
disable_test t0027-auto-crlf
|
||||
disable_test t7513-interpret-trailers
|
||||
disable_test t7703-repack-geometric
|
||||
`,
|
||||
Check: []string{
|
||||
"-C t",
|
||||
|
||||
@@ -17,10 +17,6 @@ func (t Toolchain) newSPIRVHeaders() (pkg.Artifact, string) {
|
||||
"vulkan-sdk-"+version,
|
||||
checksum,
|
||||
), nil, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
},
|
||||
|
||||
// upstream has no tests
|
||||
SkipTest: true,
|
||||
}), version
|
||||
@@ -67,7 +63,6 @@ func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
|
||||
checksum,
|
||||
), nil, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
{"SPIRV-Headers_SOURCE_DIR", "/system"},
|
||||
},
|
||||
},
|
||||
@@ -109,7 +104,6 @@ func (t Toolchain) newGlslang() (pkg.Artifact, string) {
|
||||
Chmod: true,
|
||||
}, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
{"BUILD_SHARED_LIBS", "ON"},
|
||||
{"ALLOW_EXTERNAL_SPIRV_TOOLS", "ON"},
|
||||
},
|
||||
@@ -132,3 +126,114 @@ func init() {
|
||||
ID: 205796,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "22.1.2"
|
||||
checksum = "JZAaV5ewYcm-35YA_U2BM2IcsQouZtX1BLZR0zh2vSlfEXMsT5OCtY4Gh5RJkcGy"
|
||||
)
|
||||
skipChecks := []string{
|
||||
// error: line 13: OpTypeCooperativeMatrixKHR Scope is limited to Workgroup and Subgroup
|
||||
"cooperative_matrix_constant_null.spvasm",
|
||||
}
|
||||
|
||||
switch arch {
|
||||
case "arm64":
|
||||
skipChecks = append(skipChecks,
|
||||
// LLVM ERROR: unsupported calling convention
|
||||
"DebugInfo/COFF/no-cus.ll",
|
||||
"DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll",
|
||||
"DebugInfo/Generic/2009-11-10-CurrentFn.ll",
|
||||
"DebugInfo/Generic/2010-01-05-DbgScope.ll",
|
||||
"DebugInfo/Generic/2010-03-12-llc-crash.ll",
|
||||
"DebugInfo/Generic/2010-03-24-MemberFn.ll",
|
||||
"DebugInfo/Generic/2010-04-19-FramePtr.ll",
|
||||
"DebugInfo/Generic/2010-06-29-InlinedFnLocalVar.ll",
|
||||
"DebugInfo/Generic/2010-10-01-crash.ll",
|
||||
"DebugInfo/Generic/PR20038.ll",
|
||||
"DebugInfo/Generic/constant-pointers.ll",
|
||||
"DebugInfo/Generic/dead-argument-order.ll",
|
||||
"DebugInfo/Generic/debug-info-eis-option.ll",
|
||||
"DebugInfo/Generic/def-line.ll",
|
||||
"DebugInfo/Generic/discriminator.ll",
|
||||
"DebugInfo/Generic/dwarf-public-names.ll",
|
||||
"DebugInfo/Generic/enum.ll",
|
||||
"DebugInfo/Generic/func-using-decl.ll",
|
||||
"DebugInfo/Generic/global.ll",
|
||||
"DebugInfo/Generic/imported-name-inlined.ll",
|
||||
"DebugInfo/Generic/incorrect-variable-debugloc1.ll",
|
||||
"DebugInfo/Generic/inline-scopes.ll",
|
||||
"DebugInfo/Generic/inlined-arguments.ll",
|
||||
"DebugInfo/Generic/inlined-vars.ll",
|
||||
"DebugInfo/Generic/linear-dbg-value.ll",
|
||||
"DebugInfo/Generic/linkage-name-abstract.ll",
|
||||
"DebugInfo/Generic/member-order.ll",
|
||||
"DebugInfo/Generic/missing-abstract-variable.ll",
|
||||
"DebugInfo/Generic/multiline.ll",
|
||||
"DebugInfo/Generic/namespace_function_definition.ll",
|
||||
"DebugInfo/Generic/namespace_inline_function_definition.ll",
|
||||
"DebugInfo/Generic/noscopes.ll",
|
||||
"DebugInfo/Generic/ptrsize.ll",
|
||||
"DebugInfo/Generic/restrict.ll",
|
||||
"DebugInfo/Generic/two-cus-from-same-file.ll",
|
||||
"DebugInfo/Generic/version.ll",
|
||||
"DebugInfo/LocalAddressSpace.ll",
|
||||
"DebugInfo/UnknownBaseType.ll",
|
||||
"DebugInfo/expr-opcode.ll",
|
||||
)
|
||||
}
|
||||
|
||||
return t.NewPackage("spirv-llvm-translator", version, newFromGitHub(
|
||||
"KhronosGroup/SPIRV-LLVM-Translator",
|
||||
"v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"remove-early-prefix", `diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index c000a77e..86f79b03 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -172,5 +172,5 @@ install(
|
||||
FILES
|
||||
${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc
|
||||
DESTINATION
|
||||
- ${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
||||
+ lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
|
||||
)
|
||||
`},
|
||||
},
|
||||
|
||||
// litArgs emits shell syntax
|
||||
ScriptEarly: `
|
||||
export LIT_OPTS=` + litArgs(true, skipChecks...) + `
|
||||
`,
|
||||
}, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_SKIP_BUILD_RPATH", "ON"},
|
||||
{"BUILD_SHARED_LIBS", "ON"},
|
||||
{"LLVM_SPIRV_ENABLE_LIBSPIRV_DIS", "ON"},
|
||||
{"LLVM_EXTERNAL_SPIRV_HEADERS_SOURCE_DIR", "/system"},
|
||||
{"LLVM_EXTERNAL_LIT", "/system/bin/lit"},
|
||||
{"LLVM_INCLUDE_TESTS", "ON"},
|
||||
},
|
||||
},
|
||||
Bash,
|
||||
LIT,
|
||||
|
||||
SPIRVTools,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[SPIRVLLVMTranslator] = Metadata{
|
||||
f: Toolchain.newSPIRVLLVMTranslator,
|
||||
|
||||
Name: "spirv-llvm-translator",
|
||||
Description: "bi-directional translation between SPIR-V and LLVM IR",
|
||||
Website: "https://github.com/KhronosGroup/SPIRV-LLVM-Translator",
|
||||
|
||||
Dependencies: P{
|
||||
SPIRVTools,
|
||||
},
|
||||
|
||||
ID: 227273,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -843,7 +842,7 @@ func (t Toolchain) newGnuTLS() (pkg.Artifact, string) {
|
||||
)
|
||||
|
||||
var configureExtra []KV
|
||||
switch runtime.GOARCH {
|
||||
switch arch {
|
||||
case "arm64":
|
||||
configureExtra = []KV{
|
||||
{"disable-hardware-acceleration"},
|
||||
@@ -1148,7 +1147,7 @@ func (t Toolchain) newGCC() (pkg.Artifact, string) {
|
||||
)
|
||||
|
||||
var configureExtra []KV
|
||||
switch runtime.GOARCH {
|
||||
switch arch {
|
||||
case "amd64", "arm64":
|
||||
configureExtra = append(configureExtra, KV{"with-multilib-list", "''"})
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"slices"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
@@ -35,6 +34,10 @@ func (t Toolchain) newGo(
|
||||
script string,
|
||||
extra ...pkg.Artifact,
|
||||
) pkg.Artifact {
|
||||
name := "all"
|
||||
if presetOpts&OptSkipCheck != 0 {
|
||||
name = "make"
|
||||
}
|
||||
return t.New("go"+version, 0, t.AppendPresets(extra,
|
||||
Bash,
|
||||
), nil, slices.Concat([]string{
|
||||
@@ -48,7 +51,7 @@ cp -r /usr/src/go /work/system
|
||||
cd /work/system/go/src
|
||||
chmod -R +w ..
|
||||
`+script+`
|
||||
./all.bash
|
||||
./`+name+`.bash
|
||||
|
||||
mkdir /work/system/bin
|
||||
ln -s \
|
||||
@@ -69,7 +72,7 @@ func (t Toolchain) newGoLatest() (pkg.Artifact, string) {
|
||||
|
||||
finalEnv []string
|
||||
)
|
||||
switch runtime.GOARCH {
|
||||
switch arch {
|
||||
case "amd64":
|
||||
bootstrapExtra = append(bootstrapExtra, t.newGoBootstrap())
|
||||
|
||||
@@ -79,7 +82,7 @@ func (t Toolchain) newGoLatest() (pkg.Artifact, string) {
|
||||
finalEnv = append(finalEnv, "CGO_ENABLED=0")
|
||||
|
||||
default:
|
||||
panic("unsupported target " + runtime.GOARCH)
|
||||
panic("unsupported target " + arch)
|
||||
}
|
||||
|
||||
go119 := t.newGo(
|
||||
@@ -104,7 +107,7 @@ echo \
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
||||
cmd/link/internal/`+arch+`/obj.go
|
||||
|
||||
rm \
|
||||
crypto/tls/handshake_client_test.go \
|
||||
@@ -122,17 +125,17 @@ echo \
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
||||
cmd/link/internal/`+arch+`/obj.go
|
||||
`, go121,
|
||||
)
|
||||
|
||||
go125 := t.newGo(
|
||||
"1.25.9",
|
||||
"gShJb9uOMk5AxqPSwvn53ZO56S6PyP6nfojzrHUiJ3krAvrgjJpYa6-DPA-jxbpN",
|
||||
"1.25.10",
|
||||
"TwKwatkpwal-j9U2sDSRPEdM3YesI4Gm88YgGV59wtU-L85K9gA7UPy9SCxn6PMb",
|
||||
[]string{"CGO_ENABLED=0"}, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
||||
cmd/link/internal/`+arch+`/obj.go
|
||||
|
||||
rm \
|
||||
os/root_unix_test.go \
|
||||
@@ -141,8 +144,8 @@ rm \
|
||||
)
|
||||
|
||||
const (
|
||||
version = "1.26.2"
|
||||
checksum = "v-6BE89_1g3xYf-9oIYpJKFXlo3xKHYJj2_VGkaUq8ZVkIVQmLwrto-xGG03OISH"
|
||||
version = "1.26.3"
|
||||
checksum = "lEiFocZFnN5fKvZzmwVdqc9pYUjAuhzqZGbuiOqxUP4XdcY8yECisKcqsQ_eNn1N"
|
||||
)
|
||||
return t.newGo(
|
||||
version,
|
||||
@@ -150,7 +153,7 @@ rm \
|
||||
finalEnv, `
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
||||
cmd/link/internal/`+arch+`/obj.go
|
||||
sed -i \
|
||||
's/cpu.X86.HasAVX512VBMI/& \&\& cpu.X86.HasPOPCNT/' \
|
||||
internal/runtime/gc/scan/scan_amd64.go
|
||||
|
||||
@@ -7,9 +7,8 @@ func (t Toolchain) newHakurei(
|
||||
withHostname bool,
|
||||
) pkg.Artifact {
|
||||
hostname := `
|
||||
echo '# Building test helper (hostname).'
|
||||
go build -v -o /bin/hostname /usr/src/hostname/main.go
|
||||
echo
|
||||
echo 'Building test helper (hostname).'
|
||||
go build -o /bin/hostname /usr/src/hostname/main.go
|
||||
`
|
||||
if !withHostname {
|
||||
hostname = ""
|
||||
@@ -64,9 +63,9 @@ func init() {
|
||||
return t.newHakurei("", `
|
||||
mkdir -p /work/system/libexec/hakurei/
|
||||
|
||||
echo '# Building hakurei.'
|
||||
go generate -v ./...
|
||||
go build -trimpath -v -tags=rosa -o /work/system/libexec/hakurei -ldflags="-s -w
|
||||
echo "Building hakurei for $(go env GOOS)/$(go env GOARCH)."
|
||||
go generate ./...
|
||||
go build -trimpath -tags=rosa -o /work/system/libexec/hakurei -ldflags="-s -w
|
||||
-buildid=
|
||||
-linkmode external
|
||||
-extldflags=-static
|
||||
@@ -77,7 +76,7 @@ go build -trimpath -v -tags=rosa -o /work/system/libexec/hakurei -ldflags="-s -w
|
||||
" ./...
|
||||
echo
|
||||
|
||||
echo '# Testing hakurei.'
|
||||
echo '##### Testing hakurei.'
|
||||
go test -ldflags='-buildid= -linkmode external -extldflags=-static' ./...
|
||||
echo
|
||||
|
||||
|
||||
@@ -4,13 +4,13 @@ package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
const hakureiVersion = "0.4.0"
|
||||
const hakureiVersion = "0.4.1"
|
||||
|
||||
// hakureiSource is the source code of a hakurei release.
|
||||
var hakureiSource = newTar(
|
||||
"https://git.gensokyo.uk/rosa/hakurei/archive/"+
|
||||
"v"+hakureiVersion+".tar.gz",
|
||||
"wfQ9DqCW0Fw9o91wj-I55waoqzB-UqzzuC0_2h-P-1M78SgZ1WHSPCDJMth6EyC2",
|
||||
"8bHvZcjUQOXUPbKL-qq99pHFTPnn-h7j1fkJudbGs8waLm3OmkI6eHfQev5bug2y",
|
||||
pkg.TarGzip,
|
||||
)
|
||||
|
||||
|
||||
34
internal/rosa/hwdata.go
Normal file
34
internal/rosa/hwdata.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newHwdata() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.407"
|
||||
checksum = "6p1XD0CRuzt6hLfjv4ShKBW934BexmoPkRrmwxD4J63fBVCzVBRHyF8pVJdW_Xjm"
|
||||
)
|
||||
return t.NewPackage("hwdata", version, newFromGitHub(
|
||||
"vcrhonek/hwdata",
|
||||
"v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
Writable: true,
|
||||
EnterSource: true,
|
||||
}, &MakeHelper{
|
||||
// awk: fatal: cannot open file `hwdata.spec' for reading: No such file or directory
|
||||
InPlace: true,
|
||||
|
||||
// lspci: Unknown option 'A' (see "lspci --help")
|
||||
SkipCheck: true,
|
||||
}), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Hwdata] = Metadata{
|
||||
f: Toolchain.newHwdata,
|
||||
|
||||
Name: "hwdata",
|
||||
Description: "contains various hardware identification and configuration data",
|
||||
Website: "https://github.com/vcrhonek/hwdata",
|
||||
|
||||
ID: 5387,
|
||||
}
|
||||
}
|
||||
100
internal/rosa/libarchive.go
Normal file
100
internal/rosa/libarchive.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibarchive() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "3.8.7"
|
||||
checksum = "CUJK4MDQmZmATClgQBH2Wt-7Ts4iiSUlg1J_TVb6-5IK3rVUgVLIMc5k-bnWB9w3"
|
||||
)
|
||||
return t.NewPackage("libarchive", version, newFromGitHub(
|
||||
"libarchive/libarchive",
|
||||
"v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
Paths: []pkg.ExecPath{
|
||||
pkg.Path(AbsUsrSrc.Append(
|
||||
"CTestCustom.cmake",
|
||||
), false, pkg.NewFile("CTestCustom.cmake", []byte(`
|
||||
list(APPEND CTEST_CUSTOM_TESTS_IGNORE
|
||||
"libarchive_test_archive_string_conversion_fail_c"
|
||||
"libarchive_test_archive_string_conversion_fail_latin1"
|
||||
"libarchive_test_archive_string_update_utf8_koi8"
|
||||
"libarchive_test_gnutar_filename_encoding_KOI8R_UTF8"
|
||||
"libarchive_test_gnutar_filename_encoding_KOI8R_CP866"
|
||||
"libarchive_test_gnutar_filename_encoding_CP1251_UTF8"
|
||||
"libarchive_test_gnutar_filename_encoding_Russian_Russia"
|
||||
"libarchive_test_gnutar_filename_encoding_EUCJP_UTF8"
|
||||
"libarchive_test_gnutar_filename_encoding_EUCJP_CP932"
|
||||
"libarchive_test_gnutar_filename_encoding_CP932_UTF8"
|
||||
"libarchive_test_pax_filename_encoding_KOI8R"
|
||||
"libarchive_test_pax_filename_encoding_CP1251"
|
||||
"libarchive_test_pax_filename_encoding_EUCJP"
|
||||
"libarchive_test_pax_filename_encoding_CP932"
|
||||
"libarchive_test_read_format_cpio_filename_UTF8_eucJP"
|
||||
"libarchive_test_read_format_cpio_filename_CP866_KOI8R"
|
||||
"libarchive_test_read_format_cpio_filename_KOI8R_CP866"
|
||||
"libarchive_test_read_format_cpio_filename_UTF8_KOI8R"
|
||||
"libarchive_test_read_format_cpio_filename_UTF8_CP866"
|
||||
"libarchive_test_read_format_cpio_filename_eucJP_CP932"
|
||||
"libarchive_test_read_format_cpio_filename_UTF8_CP932"
|
||||
"libarchive_test_read_format_cpio_filename_CP866_CP1251"
|
||||
"libarchive_test_read_format_cpio_filename_CP866_CP1251_win"
|
||||
"libarchive_test_read_format_cpio_filename_KOI8R_CP1251"
|
||||
"libarchive_test_read_format_cpio_filename_UTF8_CP1251"
|
||||
"libarchive_test_read_format_gtar_filename_CP866_KOI8R"
|
||||
"libarchive_test_read_format_gtar_filename_KOI8R_CP866"
|
||||
"libarchive_test_read_format_gtar_filename_eucJP_CP932"
|
||||
"libarchive_test_read_format_gtar_filename_CP866_CP1251"
|
||||
"libarchive_test_read_format_gtar_filename_CP866_CP1251_win"
|
||||
"libarchive_test_read_format_gtar_filename_KOI8R_CP1251"
|
||||
"libarchive_test_read_format_rar_unicode_CP932"
|
||||
"libarchive_test_read_format_zip_filename_CP932_eucJP"
|
||||
"libarchive_test_read_format_zip_filename_UTF8_eucJP"
|
||||
"libarchive_test_read_format_zip_filename_CP866_KOI8R"
|
||||
"libarchive_test_read_format_zip_filename_KOI8R_CP866"
|
||||
"libarchive_test_read_format_zip_filename_UTF8_KOI8R"
|
||||
"libarchive_test_read_format_zip_filename_UTF8_CP866"
|
||||
"libarchive_test_read_format_zip_filename_CP932_CP932"
|
||||
"libarchive_test_read_format_zip_filename_UTF8_CP932"
|
||||
"libarchive_test_read_format_zip_filename_CP866_CP1251"
|
||||
"libarchive_test_read_format_zip_filename_CP866_CP1251_win"
|
||||
"libarchive_test_read_format_zip_filename_KOI8R_CP1251"
|
||||
"libarchive_test_read_format_zip_filename_UTF8_CP1251"
|
||||
"libarchive_test_ustar_filename_encoding_KOI8R_UTF8"
|
||||
"libarchive_test_ustar_filename_encoding_KOI8R_CP866"
|
||||
"libarchive_test_ustar_filename_encoding_CP1251_UTF8"
|
||||
"libarchive_test_ustar_filename_encoding_Russian_Russia"
|
||||
"libarchive_test_ustar_filename_encoding_EUCJP_UTF8"
|
||||
"libarchive_test_ustar_filename_encoding_EUCJP_CP932"
|
||||
"libarchive_test_ustar_filename_encoding_CP932_UTF8"
|
||||
"libarchive_test_zip_filename_encoding_KOI8R"
|
||||
"libarchive_test_zip_filename_encoding_ru_RU_CP1251"
|
||||
"libarchive_test_zip_filename_encoding_Russian_Russia"
|
||||
"libarchive_test_zip_filename_encoding_EUCJP"
|
||||
"libarchive_test_zip_filename_encoding_CP932"
|
||||
"libarchive_test_read_format_cab_filename"
|
||||
"libarchive_test_read_format_lha_filename"
|
||||
"libarchive_test_read_format_tar_filename"
|
||||
"libarchive_test_read_format_ustar_filename"
|
||||
"libarchive_test_read_append_wrong_filter"
|
||||
)
|
||||
`))),
|
||||
},
|
||||
|
||||
Writable: true,
|
||||
ScriptEarly: `
|
||||
install -Dv /usr/src/CTestCustom.cmake /cure/
|
||||
`,
|
||||
}, (*CMakeHelper)(nil)), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libarchive] = Metadata{
|
||||
f: Toolchain.newLibarchive,
|
||||
|
||||
Name: "libarchive",
|
||||
Description: "multi-format archive and compression library",
|
||||
Website: "https://www.libarchive.org/",
|
||||
|
||||
ID: 1558,
|
||||
}
|
||||
}
|
||||
50
internal/rosa/libconfig.go
Normal file
50
internal/rosa/libconfig.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibconfig() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.8.2"
|
||||
checksum = "fD32hjeAZuTz98g6WYHRwsxphrgrEFqxi5Z1jlJemPckPBfxpS3i5HgshAuA6vmT"
|
||||
)
|
||||
return t.NewPackage("libconfig", version, newFromGitHub(
|
||||
"hyperrealm/libconfig",
|
||||
"v"+version,
|
||||
checksum,
|
||||
), &PackageAttr{
|
||||
Patches: []KV{
|
||||
{"disable-broken-tests", `diff --git a/tests/tests.c b/tests/tests.c
|
||||
index eba7eae..f916d2e 100644
|
||||
--- a/tests/tests.c
|
||||
+++ b/tests/tests.c
|
||||
@@ -753,7 +753,6 @@ int main(int argc, char **argv)
|
||||
int failures;
|
||||
|
||||
TT_SUITE_START(LibConfigTests);
|
||||
- TT_SUITE_TEST(LibConfigTests, ParsingAndFormatting);
|
||||
TT_SUITE_TEST(LibConfigTests, ParseInvalidFiles);
|
||||
TT_SUITE_TEST(LibConfigTests, ParseInvalidStrings);
|
||||
TT_SUITE_TEST(LibConfigTests, BigInt1);
|
||||
@@ -768,7 +767,6 @@ int main(int argc, char **argv)
|
||||
TT_SUITE_TEST(LibConfigTests, OverrideSetting);
|
||||
TT_SUITE_TEST(LibConfigTests, SettingLookups);
|
||||
TT_SUITE_TEST(LibConfigTests, ReadStream);
|
||||
- TT_SUITE_TEST(LibConfigTests, BinaryAndHex);
|
||||
TT_SUITE_RUN(LibConfigTests);
|
||||
failures = TT_SUITE_NUM_FAILURES(LibConfigTests);
|
||||
TT_SUITE_END(LibConfigTests);
|
||||
`},
|
||||
},
|
||||
}, (*CMakeHelper)(nil)), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libconfig] = Metadata{
|
||||
f: Toolchain.newLibconfig,
|
||||
|
||||
Name: "libconfig",
|
||||
Description: "a simple library for processing structured configuration files",
|
||||
Website: "https://hyperrealm.github.io/libconfig/",
|
||||
|
||||
ID: 1580,
|
||||
}
|
||||
}
|
||||
30
internal/rosa/libdisplay-info.go
Normal file
30
internal/rosa/libdisplay-info.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newLibdisplayInfo() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.3.0"
|
||||
checksum = "yjOqPUHHYgRtpqGw5RI1n2Q1_hO5j0LiFNMbjcRWV4Nf71XwwoC9fZMlKBDeLchT"
|
||||
)
|
||||
return t.NewPackage("libdisplay-info", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"emersion/libdisplay-info",
|
||||
version, checksum,
|
||||
), nil, (*MesonHelper)(nil),
|
||||
Diffutils,
|
||||
|
||||
Hwdata,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[LibdisplayInfo] = Metadata{
|
||||
f: Toolchain.newLibdisplayInfo,
|
||||
|
||||
Name: "libdisplay-info",
|
||||
Description: "EDID and DisplayID library",
|
||||
Website: "https://gitlab.freedesktop.org/emersion/libdisplay-info",
|
||||
|
||||
ID: 326668,
|
||||
}
|
||||
}
|
||||
38
internal/rosa/libpng.go
Normal file
38
internal/rosa/libpng.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
func (t Toolchain) newLibpng() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.6.58"
|
||||
checksum = "m_a5lROJH7vmF3cMjqwTUqURuQLhV1JQx2ySPzcN3VPdgDB9pG3UINsIx_mtkr-t"
|
||||
)
|
||||
return t.NewPackage("libpng", version, newTar(
|
||||
"https://downloads.sourceforge.net/project/libpng/libpng"+
|
||||
strings.Join(strings.SplitN(version, ".", 3)[:2], "")+
|
||||
"/"+version+"/libpng-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Zlib,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libpng] = Metadata{
|
||||
f: Toolchain.newLibpng,
|
||||
|
||||
Name: "libpng",
|
||||
Description: "the official PNG reference library",
|
||||
Website: "https://www.libpng.org/pub/png/libpng.html",
|
||||
|
||||
Dependencies: P{
|
||||
Zlib,
|
||||
},
|
||||
|
||||
ID: 1705,
|
||||
}
|
||||
}
|
||||
@@ -2,20 +2,173 @@ package rosa
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
|
||||
// litArgs returns [LIT] arguments for optional verbosity and check skipping.
|
||||
func litArgs(verbose bool, skipChecks ...string) string {
|
||||
args := []string{"-sv"}
|
||||
if verbose {
|
||||
args[0] = "--verbose"
|
||||
}
|
||||
|
||||
if len(skipChecks) > 0 {
|
||||
skipChecks = slices.Clone(skipChecks)
|
||||
for i, s := range skipChecks {
|
||||
s = regexp.QuoteMeta(s)
|
||||
s = strings.ReplaceAll(s, "/", "\\/")
|
||||
skipChecks[i] = s
|
||||
}
|
||||
args = append(args,
|
||||
"--filter-out='\\''"+strings.Join(skipChecks, "|")+"'\\''")
|
||||
}
|
||||
|
||||
return "'" + strings.Join(args, " ") + "'"
|
||||
}
|
||||
|
||||
func (t Toolchain) newEarlyCompilerRT() (pkg.Artifact, string) {
|
||||
version := t.Version(llvmSource)
|
||||
major, _, _ := strings.Cut(version, ".")
|
||||
return t.NewPackage("early-compiler-rt", version, t.Load(llvmSource), &PackageAttr{
|
||||
Flag: TExclusive,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"compiler-rt"},
|
||||
|
||||
Cache: []KV{
|
||||
{"ENABLE_LINKER_BUILD_ID", "ON"},
|
||||
|
||||
// libc++ not yet available
|
||||
{"CMAKE_CXX_COMPILER_TARGET", ""},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_ENABLE_RTTI", "ON"},
|
||||
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_LINK_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
|
||||
|
||||
{"COMPILER_RT_BUILD_BUILTINS", "ON"},
|
||||
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"},
|
||||
{"COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"},
|
||||
{"COMPILER_RT_SANITIZERS_TO_BUILD", "asan"},
|
||||
{"COMPILER_RT_BUILD_GWP_ASAN", "OFF"},
|
||||
|
||||
// does not work without libunwind
|
||||
{"COMPILER_RT_BUILD_CTX_PROFILE", "OFF"},
|
||||
{"COMPILER_RT_BUILD_LIBFUZZER", "OFF"},
|
||||
{"COMPILER_RT_BUILD_MEMPROF", "OFF"},
|
||||
{"COMPILER_RT_BUILD_PROFILE", "OFF"},
|
||||
{"COMPILER_RT_BUILD_XRAY", "OFF"},
|
||||
},
|
||||
SkipTest: true,
|
||||
Script: `
|
||||
mkdir -p "/work/system/lib/clang/` + major + `/lib/"
|
||||
ln -s \
|
||||
"../../../${ROSA_TRIPLE}" \
|
||||
"/work/system/lib/clang/` + major + `/lib/"
|
||||
|
||||
ln -s \
|
||||
"clang_rt.crtbegin-` + linuxArch() + `.o" \
|
||||
"/work/system/lib/${ROSA_TRIPLE}/crtbeginS.o"
|
||||
ln -s \
|
||||
"clang_rt.crtend-` + linuxArch() + `.o" \
|
||||
"/work/system/lib/${ROSA_TRIPLE}/crtendS.o"
|
||||
`,
|
||||
},
|
||||
Python,
|
||||
|
||||
muslHeaders,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[earlyCompilerRT] = Metadata{
|
||||
f: Toolchain.newEarlyCompilerRT,
|
||||
|
||||
Name: "early-compiler-rt",
|
||||
Description: "early LLVM runtime: compiler-rt",
|
||||
|
||||
Dependencies: P{
|
||||
Musl,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newEarlyRuntimes() (pkg.Artifact, string) {
|
||||
version := t.Version(llvmSource)
|
||||
return t.NewPackage("early-runtimes", version, t.Load(llvmSource), &PackageAttr{
|
||||
Flag: TExclusive,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"runtimes"},
|
||||
|
||||
Cache: []KV{
|
||||
{"ENABLE_LINKER_BUILD_ID", "ON"},
|
||||
|
||||
// libc++ not yet available
|
||||
{"CMAKE_CXX_COMPILER_WORKS", "ON"},
|
||||
|
||||
{"LLVM_HOST_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_DEFAULT_TARGET_TRIPLE", `"${ROSA_TRIPLE}"`},
|
||||
{"LLVM_ENABLE_RTTI", "ON"},
|
||||
{"LLVM_BUILD_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_LINK_LLVM_DYLIB", "ON"},
|
||||
{"LLVM_ENABLE_RUNTIMES", "'libunwind;libcxx;libcxxabi'"},
|
||||
|
||||
{"LIBUNWIND_ENABLE_ASSERTIONS", "OFF"},
|
||||
{"LIBUNWIND_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXX_HAS_MUSL_LIBC", "ON"},
|
||||
{"LIBCXX_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXX_CXX_ABI", "libcxxabi"},
|
||||
{"LIBCXX_ENABLE_STATIC_ABI_LIBRARY", "OFF"},
|
||||
{"LIBCXX_HARDENING_MODE", "fast"},
|
||||
{"LIBCXX_HAS_ATOMIC_LIB", "OFF"},
|
||||
{"LIBCXXABI_USE_COMPILER_RT", "ON"},
|
||||
{"LIBCXXABI_USE_LLVM_UNWINDER", "ON"},
|
||||
{"LIBCXXABI_ENABLE_STATIC_UNWINDER", "OFF"},
|
||||
{"LIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL", "OFF"},
|
||||
|
||||
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_ZSTD", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_LIBXML2", "OFF"},
|
||||
},
|
||||
SkipTest: true,
|
||||
},
|
||||
Python,
|
||||
|
||||
Zlib,
|
||||
Zstd,
|
||||
earlyCompilerRT,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[earlyRuntimes] = Metadata{
|
||||
f: Toolchain.newEarlyRuntimes,
|
||||
|
||||
Name: "early-runtimes",
|
||||
Description: "early LLVM runtimes: libunwind, libcxx, libcxxabi",
|
||||
|
||||
Dependencies: P{
|
||||
earlyCompilerRT,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "22.1.4"
|
||||
checksum = "Bk3t-tV5sD5T0bqefFMcLeFuAwXnhFipywZmqst5hAZs97QQWGKB_5XyAFjj5tDB"
|
||||
)
|
||||
var early PArtifact = muslHeaders
|
||||
if t.isStage0() {
|
||||
// The LLVM build system uses the system installation when building with
|
||||
// LLVM_LINK_LLVM_DYLIB, since it builds runtimes after the fact, using
|
||||
// the just-built toolchain. This is unacceptable in stage0 due to the
|
||||
// potential version difference. Later stages bootstrap off of runtimes
|
||||
// of its previous stage via 3-stage determinism.
|
||||
early = earlyRuntimes
|
||||
}
|
||||
|
||||
cache := []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
|
||||
{"ENABLE_LINKER_BUILD_ID", "ON"},
|
||||
{"COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"},
|
||||
{"COMPILER_RT_DEFAULT_TARGET_ONLY", "ON"},
|
||||
@@ -37,6 +190,7 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
||||
{"LLVM_ENABLE_ZLIB", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_ZSTD", "FORCE_ON"},
|
||||
{"LLVM_ENABLE_PER_TARGET_RUNTIME_DIR", "ON"},
|
||||
{"LLVM_INCLUDE_BENCHMARKS", "OFF"},
|
||||
{"CLANG_DEFAULT_RTLIB", "compiler-rt"},
|
||||
{"CLANG_DEFAULT_UNWINDLIB", "libunwind"},
|
||||
{"CLANG_DEFAULT_CXX_STDLIB", "libc++"},
|
||||
@@ -93,10 +247,14 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
||||
// unwind: fails on musl
|
||||
"eh_frame_fde_pc_range",
|
||||
}
|
||||
for i, s := range skipChecks {
|
||||
s = regexp.QuoteMeta(s)
|
||||
s = strings.ReplaceAll(s, "/", "\\/")
|
||||
skipChecks[i] = s
|
||||
switch arch {
|
||||
case "arm64":
|
||||
skipChecks = append(skipChecks,
|
||||
// LLVM: intermittently crashes
|
||||
"ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll",
|
||||
// unwind: unexpectedly passes
|
||||
"unwind_leaffunction",
|
||||
)
|
||||
}
|
||||
|
||||
if presetOpts&OptLLVMNoLTO == 0 {
|
||||
@@ -110,25 +268,20 @@ func (t Toolchain) newLLVM() (pkg.Artifact, string) {
|
||||
// symbols: clock_gettime, mallopt
|
||||
{"COMPILER_RT_INCLUDE_TESTS", "OFF"},
|
||||
|
||||
{"LLVM_LIT_ARGS", "'" + strings.Join([]string{
|
||||
"--verbose",
|
||||
"--filter-out='\\''" + strings.Join(skipChecks, "|") + "'\\''",
|
||||
}, " ") + "'"},
|
||||
{"LLVM_BUILD_TESTS", "ON"},
|
||||
{"LLVM_LIT_ARGS", litArgs(true, skipChecks...)},
|
||||
}...)
|
||||
}
|
||||
|
||||
return t.NewPackage("llvm", version, t.NewPatchedSource("llvm", version, newFromGitHub(
|
||||
"llvm/llvm-project",
|
||||
"llvmorg-"+version,
|
||||
checksum,
|
||||
), true, llvmPatches...), nil, &CMakeHelper{
|
||||
version := t.Version(llvmSource)
|
||||
return t.NewPackage("llvm", version, t.Load(llvmSource), nil, &CMakeHelper{
|
||||
Append: []string{"llvm"},
|
||||
|
||||
Cache: cache,
|
||||
Script: `
|
||||
ln -s ld.lld /work/system/bin/ld
|
||||
|
||||
ln -s clang /work/system/bin/cc
|
||||
ln -s clang /work/system/bin/cpp
|
||||
ln -s clang++ /work/system/bin/c++
|
||||
`,
|
||||
|
||||
@@ -159,11 +312,31 @@ ninja ` + jobsFlagE + ` check-all
|
||||
|
||||
Zlib,
|
||||
Zstd,
|
||||
muslHeaders,
|
||||
early,
|
||||
KernelHeaders,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
const (
|
||||
version = "22.1.4"
|
||||
checksum = "Bk3t-tV5sD5T0bqefFMcLeFuAwXnhFipywZmqst5hAZs97QQWGKB_5XyAFjj5tDB"
|
||||
)
|
||||
|
||||
artifactsM[llvmSource] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
return t.NewPatchedSource("llvm", version, newFromGitHub(
|
||||
"llvm/llvm-project",
|
||||
"llvmorg-"+version,
|
||||
checksum,
|
||||
), true, llvmPatches...), version
|
||||
},
|
||||
|
||||
Name: "llvm-project",
|
||||
Description: "LLVM monorepo with Rosa OS patches",
|
||||
|
||||
ID: 1830,
|
||||
}
|
||||
|
||||
artifactsM[LLVM] = Metadata{
|
||||
f: Toolchain.newLLVM,
|
||||
|
||||
@@ -176,7 +349,5 @@ func init() {
|
||||
Zstd,
|
||||
Musl,
|
||||
},
|
||||
|
||||
ID: 1830,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,8 +90,23 @@ index 8ac8d4eb9181..e46b04a898ca 100644
|
||||
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
|
||||
`},
|
||||
|
||||
{"path-system-libraries", `diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
|
||||
index d525b417b4ea..fdc411f2239c 100644
|
||||
{"path-system-libraries", `diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
|
||||
index cb6a9b242421..b8d31690d1af 100644
|
||||
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
|
||||
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
|
||||
@@ -2314,6 +2314,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
|
||||
Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");
|
||||
}
|
||||
|
||||
+ if (TargetTriple.getVendor() == llvm::Triple::Rosa) {
|
||||
+ Prefixes.push_back(concat(SysRoot, "/system"));
|
||||
+ }
|
||||
+
|
||||
// Fall back to /usr which is used by most non-Solaris systems.
|
||||
Prefixes.push_back(concat(SysRoot, "/usr"));
|
||||
}
|
||||
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
|
||||
index d525b417b4ea..2b93f401733e 100644
|
||||
--- a/clang/lib/Driver/ToolChains/Linux.cpp
|
||||
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
|
||||
@@ -302,6 +302,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
@@ -102,18 +117,7 @@ index d525b417b4ea..fdc411f2239c 100644
|
||||
|
||||
if (IsCSKY && !SelectedMultilibs.empty())
|
||||
SysRoot = SysRoot + SelectedMultilibs.back().osSuffix();
|
||||
@@ -337,12 +338,23 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));
|
||||
const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
|
||||
|
||||
+ if (IsRosa) {
|
||||
+ ExtraOpts.push_back("-rpath");
|
||||
+ ExtraOpts.push_back("/system/lib");
|
||||
+ ExtraOpts.push_back("-rpath");
|
||||
+ ExtraOpts.push_back(concat("/system/lib", Triple.str()));
|
||||
+ }
|
||||
+
|
||||
// mips32: Debian multilib, we use /libo32, while in other case, /lib is
|
||||
@@ -341,8 +342,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
// used. We need add both libo32 and /lib.
|
||||
if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel) {
|
||||
Generic_GCC::AddMultilibPaths(D, SysRoot, "libo32", MultiarchTriple, Paths);
|
||||
@@ -128,7 +132,7 @@ index d525b417b4ea..fdc411f2239c 100644
|
||||
}
|
||||
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
|
||||
|
||||
@@ -360,18 +372,30 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
@@ -360,18 +365,30 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
Paths);
|
||||
}
|
||||
|
||||
@@ -164,7 +168,7 @@ index d525b417b4ea..fdc411f2239c 100644
|
||||
}
|
||||
|
||||
ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
|
||||
@@ -572,6 +596,9 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
|
||||
@@ -572,6 +589,9 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
|
||||
return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker";
|
||||
}
|
||||
if (Triple.isMusl()) {
|
||||
@@ -174,18 +178,5 @@ index d525b417b4ea..fdc411f2239c 100644
|
||||
std::string ArchName;
|
||||
bool IsArm = false;
|
||||
|
||||
diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp
|
||||
index f484d6f33ad8..dca55e72d67e 100644
|
||||
--- a/clang/tools/clang-installapi/Options.cpp
|
||||
+++ b/clang/tools/clang-installapi/Options.cpp
|
||||
@@ -514,7 +514,7 @@ bool Options::processFrontendOptions(InputArgList &Args) {
|
||||
FEOpts.FwkPaths = std::move(FrameworkPaths);
|
||||
|
||||
// Add default framework/library paths.
|
||||
- PathSeq DefaultLibraryPaths = {"/usr/lib", "/usr/local/lib"};
|
||||
+ PathSeq DefaultLibraryPaths = {"/usr/lib", "/system/lib", "/usr/local/lib"};
|
||||
PathSeq DefaultFrameworkPaths = {"/Library/Frameworks",
|
||||
"/System/Library/Frameworks"};
|
||||
|
||||
`},
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ cd "$(mktemp -d)"
|
||||
meson setup \
|
||||
` + strings.Join(slices.Collect(func(yield func(string) bool) {
|
||||
for _, v := range append([]KV{
|
||||
{"wrap-mode", "nodownload"},
|
||||
{"wrap-mode", "nofallback"},
|
||||
{"prefix", "/system"},
|
||||
{"buildtype", "release"},
|
||||
}, attr.Setup...) {
|
||||
|
||||
@@ -7,6 +7,10 @@ func (t Toolchain) newMksh() (pkg.Artifact, string) {
|
||||
version = "59c"
|
||||
checksum = "0Zj-k4nXEu3IuJY4lvwD2OrC2t27GdZj8SPy4DoaeuBRH1padWb7oREpYgwY8JNq"
|
||||
)
|
||||
scriptTest := "./test.sh -C regress:no-ctty\n"
|
||||
if presetOpts&OptSkipCheck != 0 {
|
||||
scriptTest = ""
|
||||
}
|
||||
return t.New("mksh-"+version, 0, t.AppendPresets(nil,
|
||||
Perl,
|
||||
Coreutils,
|
||||
@@ -18,8 +22,7 @@ cd "$(mktemp -d)"
|
||||
sh /usr/src/mksh/Build.sh -r
|
||||
CPPFLAGS="${CPPFLAGS} -DMKSH_BINSHPOSIX -DMKSH_BINSHREDUCED" \
|
||||
sh /usr/src/mksh/Build.sh -r -L
|
||||
./test.sh -C regress:no-ctty
|
||||
|
||||
`+scriptTest+`
|
||||
mkdir -p /work/system/bin/
|
||||
cp -v mksh /work/system/bin/
|
||||
cp -v lksh /work/system/bin/sh
|
||||
|
||||
@@ -53,6 +53,23 @@ rmdir -v /work/lib
|
||||
Chmod: true,
|
||||
|
||||
Env: env,
|
||||
|
||||
Patches: []KV{
|
||||
{"ldso-rosa", `diff --git a/ldso/dynlink.c b/ldso/dynlink.c
|
||||
index 715948f4..c2fece68 100644
|
||||
--- a/ldso/dynlink.c
|
||||
+++ b/ldso/dynlink.c
|
||||
@@ -1157,7 +1157,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
|
||||
sys_path = "";
|
||||
}
|
||||
}
|
||||
- if (!sys_path) sys_path = "/lib:/usr/local/lib:/usr/lib";
|
||||
+ if (!sys_path) sys_path = "/system/lib:/system/lib/" LDSO_ARCH "-rosa-linux-musl:/lib:/usr/local/lib:/usr/lib";
|
||||
fd = path_open(name, sys_path, buf, sizeof buf);
|
||||
}
|
||||
pathname = buf;
|
||||
`},
|
||||
},
|
||||
}, &helper,
|
||||
Coreutils,
|
||||
), version
|
||||
|
||||
@@ -351,6 +351,29 @@ func init() {
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
artifactsM[LIT] = Metadata{
|
||||
f: func(t Toolchain) (pkg.Artifact, string) {
|
||||
version := t.Version(LLVM)
|
||||
return t.NewPackage("lit", version, t.Load(llvmSource), nil, &PipHelper{
|
||||
Append: []string{"llvm", "utils", "lit"},
|
||||
// already checked during llvm
|
||||
SkipCheck: true,
|
||||
},
|
||||
PythonSetuptools,
|
||||
), version
|
||||
},
|
||||
|
||||
Name: "lit",
|
||||
Description: "a portable tool for executing LLVM and Clang style test suites",
|
||||
Website: "https://llvm.org/docs/CommandGuide/lit.html",
|
||||
|
||||
Dependencies: P{
|
||||
Python,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "1.1.1"
|
||||
@@ -561,3 +584,24 @@ func init() {
|
||||
}, P{PythonSetuptools},
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
const (
|
||||
version = "3.00"
|
||||
checksum = "4qfCMFKp0fLsRsloOAF780tXX_Ce_68RwinCmjNGObAX32WpF_iBafIKW1S1bYlA"
|
||||
)
|
||||
artifactsM[PythonPycparser] = newPythonPackage(
|
||||
"pycparser", 8175,
|
||||
"complete C99 parser in pure Python",
|
||||
"https://github.com/eliben/pycparser",
|
||||
version, newFromGitHub(
|
||||
"eliben/pycparser",
|
||||
"release_v"+version, checksum,
|
||||
), &PackageAttr{
|
||||
// test case hard codes gcc
|
||||
ScriptEarly: `
|
||||
ln -s clang /system/bin/gcc
|
||||
`,
|
||||
}, nil, P{PythonSetuptools},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ EOF
|
||||
{"disable-download"},
|
||||
{"disable-docs"},
|
||||
|
||||
{"static"},
|
||||
{"target-list-exclude", "" +
|
||||
// fails to load firmware
|
||||
"ppc-linux-user," +
|
||||
|
||||
@@ -4,7 +4,6 @@ package rosa
|
||||
import (
|
||||
"errors"
|
||||
"path"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -54,10 +53,9 @@ var (
|
||||
AbsSystem = fhs.AbsRoot.Append("system")
|
||||
)
|
||||
|
||||
// linuxArch returns the architecture name used by linux corresponding to
|
||||
// [runtime.GOARCH].
|
||||
// linuxArch returns the architecture name used by linux corresponding to arch.
|
||||
func linuxArch() string {
|
||||
switch runtime.GOARCH {
|
||||
switch arch {
|
||||
case "amd64":
|
||||
return "x86_64"
|
||||
case "arm64":
|
||||
@@ -66,11 +64,11 @@ func linuxArch() string {
|
||||
return "riscv64"
|
||||
|
||||
default:
|
||||
panic("unsupported target " + runtime.GOARCH)
|
||||
panic("unsupported target " + arch)
|
||||
}
|
||||
}
|
||||
|
||||
// triplet returns the Rosa OS host triple corresponding to [runtime.GOARCH].
|
||||
// triplet returns the Rosa OS host triple corresponding to arch.
|
||||
func triplet() string {
|
||||
return linuxArch() + "-rosa-linux-musl"
|
||||
}
|
||||
@@ -80,9 +78,9 @@ type perArch[T any] map[string]T
|
||||
|
||||
// unwrap returns the value for the current architecture.
|
||||
func (p perArch[T]) unwrap() T {
|
||||
v, ok := p[runtime.GOARCH]
|
||||
v, ok := p[arch]
|
||||
if !ok {
|
||||
panic("unsupported target " + runtime.GOARCH)
|
||||
panic("unsupported target " + arch)
|
||||
}
|
||||
return v
|
||||
}
|
||||
@@ -268,7 +266,7 @@ func (t Toolchain) New(
|
||||
support = append(support, extra...)
|
||||
support = append(support, cureEtc{})
|
||||
if t == toolchainStage0 {
|
||||
support = append(support, NewStage0())
|
||||
support = append(support, t.Load(stage0Dist))
|
||||
} else {
|
||||
support = append(support, _toolchainBusybox.New("gentoo", 0, nil, nil, nil, `
|
||||
tar -C /work -xf /usr/src/stage3.tar.xz
|
||||
@@ -327,7 +325,7 @@ mkdir -vp /work/system/bin
|
||||
}
|
||||
|
||||
return pkg.NewExec(
|
||||
name, knownChecksum, pkg.ExecTimeoutMax, flag&TExclusive != 0,
|
||||
name, arch, knownChecksum, pkg.ExecTimeoutMax, flag&TExclusive != 0,
|
||||
fhs.AbsRoot, env,
|
||||
AbsSystem.Append("bin", "sh"),
|
||||
[]string{"sh", absCureScript.String()},
|
||||
|
||||
@@ -28,7 +28,7 @@ var (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
rosa.DropCaches(rosa.OptLLVMNoLTO)
|
||||
rosa.DropCaches("", rosa.OptLLVMNoLTO)
|
||||
container.TryArgv0(nil)
|
||||
|
||||
code := m.Run()
|
||||
@@ -61,7 +61,7 @@ func getCache(t *testing.T) *pkg.Cache {
|
||||
msg := message.New(log.New(os.Stderr, "rosa: ", 0))
|
||||
msg.SwapVerbose(true)
|
||||
|
||||
if buildTestCache, err = pkg.Open(ctx, msg, 0, 0, 0, a); err != nil {
|
||||
if buildTestCache, err = pkg.Open(ctx, msg, pkg.CSuppressInit, 0, 0, a); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -94,14 +94,14 @@ func TestCureAll(t *testing.T) {
|
||||
}
|
||||
|
||||
func BenchmarkStage3(b *testing.B) {
|
||||
flags := rosa.Flags()
|
||||
b.Cleanup(func() { rosa.DropCaches(flags) })
|
||||
arch, flags := rosa.Arch(), rosa.Flags()
|
||||
b.Cleanup(func() { rosa.DropCaches(arch, flags) })
|
||||
|
||||
for b.Loop() {
|
||||
rosa.Std.Load(rosa.LLVM)
|
||||
|
||||
b.StopTimer()
|
||||
rosa.DropCaches(0)
|
||||
rosa.DropCaches("", 0)
|
||||
b.StartTimer()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"hakurei.app/fhs"
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
@@ -32,24 +30,32 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
// stage0 stores the tarball unpack artifact.
|
||||
stage0 pkg.Artifact
|
||||
// stage0Once is for lazy initialisation of stage0.
|
||||
stage0Once sync.Once
|
||||
)
|
||||
|
||||
// NewStage0 returns a stage0 distribution created from curing [Stage0].
|
||||
func NewStage0() pkg.Artifact {
|
||||
stage0Once.Do(func() {
|
||||
stage0 = newTar(
|
||||
"https://hakurei.app/seed/20260429/"+
|
||||
func init() {
|
||||
const version = "20260504"
|
||||
artifactsM[stage0Dist] = Metadata{
|
||||
f: func(Toolchain) (pkg.Artifact, string) {
|
||||
return newTar(
|
||||
"https://hakurei.app/seed/"+version+"/"+
|
||||
"stage0-"+triplet()+".tar.bz2",
|
||||
perArch[string]{
|
||||
"amd64": "ldz-WkSx2wxUK4ndi-tlaaU8ykOowbpGRcBsciAcIDdnX6-QfzQg_se3lsZYuzuK",
|
||||
"amd64": "IQjFDkiAVLo1XzflgMMiLP3gnVY2hhDMTzl-QqJDCQhcLQ3lLtRzjI5WCxGyW_lk",
|
||||
"arm64": "6fmwl2Umx2QssKQvxxb1JOGkAjzfA_MXKku0jVdGjYGb35OvwEVA5NYtd0HIy3yH",
|
||||
"riscv64": "Z2ODV0rIoo9iQRUIu35bsaOBeXc_9qQfGcyb2aGneatzNUJlXh5emSpEV2bOklUL",
|
||||
}.unwrap(),
|
||||
pkg.TarBzip2,
|
||||
)
|
||||
})
|
||||
return stage0
|
||||
), version
|
||||
},
|
||||
|
||||
Name: "stage0-dist",
|
||||
Description: "Rosa OS stage0 bootstrap seed",
|
||||
}
|
||||
}
|
||||
|
||||
// HasStage0 returns whether a stage0 distribution is available.
|
||||
func HasStage0() (ok bool) {
|
||||
func() {
|
||||
defer func() { ok = recover() == nil }()
|
||||
toolchainStage0.Load(stage0Dist)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package rosa
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"hakurei.app/internal/pkg"
|
||||
)
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newTamaGo() (pkg.Artifact, string) {
|
||||
const (
|
||||
@@ -26,7 +22,7 @@ chmod -R +w ..
|
||||
|
||||
sed -i \
|
||||
's,/lib/ld-musl-`+linuxArch()+`.so.1,/system/bin/linker,' \
|
||||
cmd/link/internal/`+runtime.GOARCH+`/obj.go
|
||||
cmd/link/internal/`+arch+`/obj.go
|
||||
sed -i \
|
||||
's/cpu.X86.HasAVX512VBMI/& \&\& cpu.X86.HasPOPCNT/' \
|
||||
internal/runtime/gc/scan/scan_amd64.go
|
||||
|
||||
@@ -26,19 +26,50 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXproto() (pkg.Artifact, string) {
|
||||
func (t Toolchain) newLibxtrans() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "7.0.31"
|
||||
checksum = "Cm69urWY5RctKpR78eGzuwrjDEfXGkvHRdodj6sjypOGy5FF4-lmnUttVHYV1ydg"
|
||||
version = "1.6.0"
|
||||
checksum = "1cxDCF59fLf1HyGDMcjR1L50ZbjD0RTTEDUpOJYcHXu6HUK_Ds0x-KREY7rLNxu9"
|
||||
)
|
||||
return t.NewPackage("xproto", version, newTar(
|
||||
"https://www.x.org/releases/individual/proto/"+
|
||||
"xproto-"+version+".tar.bz2",
|
||||
return t.NewPackage("libxtrans", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libxtrans",
|
||||
"xtrans-"+version,
|
||||
checksum,
|
||||
pkg.TarBzip2,
|
||||
), nil, &MakeHelper{
|
||||
// ancient configure script
|
||||
Generate: "autoreconf -if",
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libxtrans] = Metadata{
|
||||
f: Toolchain.newLibxtrans,
|
||||
|
||||
Name: "libxtrans",
|
||||
Description: "X Window System Protocols Transport layer shared code",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxtrans",
|
||||
|
||||
ID: 13441,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXorgProto() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "2025.1"
|
||||
checksum = "pTwJiBJHKA6Rgm3cVDXy1lyvXNIUzTRaukvvYdk1xWoJ_1G-Dfjm9MyewuyIjoHz"
|
||||
)
|
||||
return t.NewPackage("xorgproto", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/proto/xorgproto",
|
||||
"xorgproto-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
PkgConfig,
|
||||
@@ -47,14 +78,14 @@ func (t Toolchain) newXproto() (pkg.Artifact, string) {
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Xproto] = Metadata{
|
||||
f: Toolchain.newXproto,
|
||||
artifactsM[XorgProto] = Metadata{
|
||||
f: Toolchain.newXorgProto,
|
||||
|
||||
Name: "xproto",
|
||||
Name: "xorgproto",
|
||||
Description: "X Window System unified protocol definitions",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/proto/xorgproto",
|
||||
|
||||
ID: 13650,
|
||||
ID: 17190,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +108,7 @@ func (t Toolchain) newLibXau() (pkg.Artifact, string) {
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
Xproto,
|
||||
XorgProto,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
@@ -89,13 +120,332 @@ func init() {
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxau",
|
||||
|
||||
Dependencies: P{
|
||||
Xproto,
|
||||
XorgProto,
|
||||
},
|
||||
|
||||
ID: 1765,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXCBProto() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.17.0"
|
||||
checksum = "_NtbKaJ_iyT7XiJz25mXQ7y-niTzE8sHPvLXZPcqtNoV_-vTzqkezJ8Hp2U1enCv"
|
||||
)
|
||||
return t.NewPackage("xcb-proto", version, newTar(
|
||||
"https://xcb.freedesktop.org/dist/xcb-proto-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Python,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[XCBProto] = Metadata{
|
||||
f: Toolchain.newXCBProto,
|
||||
|
||||
Name: "xcb-proto",
|
||||
Description: "XML-XCB protocol descriptions used by libxcb for the X11 protocol & extensions",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/proto/xcbproto",
|
||||
|
||||
ID: 13646,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXCB() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.17.0"
|
||||
checksum = "hjjsc79LpWM_hZjNWbDDS6qRQUXREjjekS6UbUsDq-RR1_AjgNDxhRvZf-1_kzDd"
|
||||
)
|
||||
return t.NewPackage("xcb", version, newTar(
|
||||
"https://xcb.freedesktop.org/dist/libxcb-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Python,
|
||||
PkgConfig,
|
||||
|
||||
XCBProto,
|
||||
LibXau,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[XCB] = Metadata{
|
||||
f: Toolchain.newXCB,
|
||||
|
||||
Name: "xcb",
|
||||
Description: "The X protocol C-language Binding",
|
||||
Website: "https://xcb.freedesktop.org/",
|
||||
|
||||
Dependencies: P{
|
||||
XCBProto,
|
||||
LibXau,
|
||||
},
|
||||
|
||||
ID: 1767,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXCBUtilKeysyms() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.4.1"
|
||||
checksum = "-EEje12UEjtFBuIjb6Fy4cxEghV20BXwQ1BLvhtvSuVcrFkp_X-ZHRM48wAspXZ4"
|
||||
)
|
||||
return t.NewPackage("xcb-util-keysyms", version, newTar(
|
||||
"https://xcb.freedesktop.org/dist/xcb-util-keysyms-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
PkgConfig,
|
||||
|
||||
XCB,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[XCBUtilKeysyms] = Metadata{
|
||||
f: Toolchain.newXCBUtilKeysyms,
|
||||
|
||||
Name: "xcb-util-keysyms",
|
||||
Description: "standard X key constants and conversion to/from keycodes",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxcb-keysyms",
|
||||
|
||||
Dependencies: P{
|
||||
XCB,
|
||||
},
|
||||
|
||||
ID: 5168,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibX11() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.8.13"
|
||||
checksum = "ARh-cuZY_U2v3DbPS1byc7ybh9NInZc-yav7SJiusk_C7408s058qWV83ocMd2pT"
|
||||
)
|
||||
return t.NewPackage("libX11", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libx11",
|
||||
"libX11-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
|
||||
Configure: []KV{
|
||||
{"enable-static"},
|
||||
{"without-xmlto"},
|
||||
},
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
Libxtrans,
|
||||
XorgProto,
|
||||
XCB,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[LibX11] = Metadata{
|
||||
f: Toolchain.newLibX11,
|
||||
|
||||
Name: "libX11",
|
||||
Description: `Core X11 protocol client library (aka "Xlib")`,
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libx11",
|
||||
|
||||
Dependencies: P{
|
||||
XCB,
|
||||
},
|
||||
|
||||
ID: 1764,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibXext() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.3.7"
|
||||
checksum = "-0wvUDaucLPLNOrK1pcKhHNoO-5nUqQyyw6JAbhx65gRjuMiNKKaF2_tcrbC_KNq"
|
||||
)
|
||||
return t.NewPackage("libXext", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libxext",
|
||||
"libXext-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
LibX11,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[LibXext] = Metadata{
|
||||
f: Toolchain.newLibXext,
|
||||
|
||||
Name: "libXext",
|
||||
Description: "Xlib-based library for common extensions to the X11 protocol",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxext",
|
||||
|
||||
Dependencies: P{
|
||||
LibX11,
|
||||
},
|
||||
|
||||
ID: 1774,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibXrender() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.9.12"
|
||||
checksum = "s6nWn-r17X_W-7anaS7wIcq5_Levf9zAigwJDD9Klp-cCJTVDhLo7GufuVOrxVP0"
|
||||
)
|
||||
return t.NewPackage("libXrender", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libxrender",
|
||||
"libXrender-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
LibX11,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[LibXrender] = Metadata{
|
||||
f: Toolchain.newLibXrender,
|
||||
|
||||
Name: "libXrender",
|
||||
Description: "Xlib library for the Render Extension to the X11 protocol",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxrender",
|
||||
|
||||
Dependencies: P{
|
||||
LibX11,
|
||||
},
|
||||
|
||||
ID: 1789,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibxshmfence() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.3.3"
|
||||
checksum = "JamExTPg81By2fs3vWdeo_dzlpBQeAwXr2sDXeHJqm9XBoLW5pamiD6FgAWtAKyA"
|
||||
)
|
||||
return t.NewPackage("libxshmfence", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libxshmfence",
|
||||
"libxshmfence-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
XorgProto,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[Libxshmfence] = Metadata{
|
||||
f: Toolchain.newLibxshmfence,
|
||||
|
||||
Name: "libxshmfence",
|
||||
Description: "shared memory 'SyncFence' synchronization primitive",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxshmfence",
|
||||
|
||||
ID: 1792,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibXxf86vm() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.1.7"
|
||||
checksum = "mS4cgKWrwz6M1Lb6Qu4ZVh8Xn2Ca_4HXPxr3LDad4iYY1LecZfeLUPW1hkp6amX_"
|
||||
)
|
||||
return t.NewPackage("libXxf86vm", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libxxf86vm",
|
||||
"libXxf86vm-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
LibXext,
|
||||
XorgProto,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[LibXxf86vm] = Metadata{
|
||||
f: Toolchain.newLibXxf86vm,
|
||||
|
||||
Name: "libXxf86vm",
|
||||
Description: "Xlib-based library for the XFree86-VidMode X extension",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxxf86vm",
|
||||
|
||||
Dependencies: P{
|
||||
LibXext,
|
||||
},
|
||||
|
||||
ID: 1799,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibXrandr() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.5.5"
|
||||
checksum = "OF7C7VC5MwnFue9UX5UnIkG1PIWvn9bBMq6d4mVyJJ_rcF0w4Kedn1lfxBsXEKAP"
|
||||
)
|
||||
return t.NewPackage("libXrandr", version, newFromGitLab(
|
||||
"gitlab.freedesktop.org",
|
||||
"xorg/lib/libxrandr",
|
||||
"libXrandr-"+version,
|
||||
checksum,
|
||||
), nil, &MakeHelper{
|
||||
Generate: "NOCONFIGURE=1 ./autogen.sh",
|
||||
},
|
||||
Automake,
|
||||
Libtool,
|
||||
PkgConfig,
|
||||
|
||||
utilMacros,
|
||||
LibXext,
|
||||
LibXrender,
|
||||
XorgProto,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[LibXrandr] = Metadata{
|
||||
f: Toolchain.newLibXrandr,
|
||||
|
||||
Name: "libXrandr",
|
||||
Description: "Xlib Resize, Rotate and Reflection (RandR) extension library",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/lib/libxrandr",
|
||||
|
||||
Dependencies: P{
|
||||
LibXext,
|
||||
LibXrender,
|
||||
},
|
||||
|
||||
ID: 1788,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newLibpciaccess() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "0.19"
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
package rosa
|
||||
|
||||
import "hakurei.app/internal/pkg"
|
||||
|
||||
func (t Toolchain) newXCBProto() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.17.0"
|
||||
checksum = "_NtbKaJ_iyT7XiJz25mXQ7y-niTzE8sHPvLXZPcqtNoV_-vTzqkezJ8Hp2U1enCv"
|
||||
)
|
||||
return t.NewPackage("xcb-proto", version, newTar(
|
||||
"https://xcb.freedesktop.org/dist/xcb-proto-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Python,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[XCBProto] = Metadata{
|
||||
f: Toolchain.newXCBProto,
|
||||
|
||||
Name: "xcb-proto",
|
||||
Description: "XML-XCB protocol descriptions used by libxcb for the X11 protocol & extensions",
|
||||
Website: "https://gitlab.freedesktop.org/xorg/proto/xcbproto",
|
||||
|
||||
ID: 13646,
|
||||
}
|
||||
}
|
||||
|
||||
func (t Toolchain) newXCB() (pkg.Artifact, string) {
|
||||
const (
|
||||
version = "1.17.0"
|
||||
checksum = "hjjsc79LpWM_hZjNWbDDS6qRQUXREjjekS6UbUsDq-RR1_AjgNDxhRvZf-1_kzDd"
|
||||
)
|
||||
return t.NewPackage("xcb", version, newTar(
|
||||
"https://xcb.freedesktop.org/dist/libxcb-"+version+".tar.gz",
|
||||
checksum,
|
||||
pkg.TarGzip,
|
||||
), nil, (*MakeHelper)(nil),
|
||||
Python,
|
||||
PkgConfig,
|
||||
|
||||
XCBProto,
|
||||
LibXau,
|
||||
), version
|
||||
}
|
||||
func init() {
|
||||
artifactsM[XCB] = Metadata{
|
||||
f: Toolchain.newXCB,
|
||||
|
||||
Name: "xcb",
|
||||
Description: "The X protocol C-language Binding",
|
||||
Website: "https://xcb.freedesktop.org/",
|
||||
|
||||
Dependencies: P{
|
||||
XCBProto,
|
||||
LibXau,
|
||||
},
|
||||
|
||||
ID: 1767,
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,6 @@ func (t Toolchain) newZlib() (pkg.Artifact, string) {
|
||||
pkg.TarGzip,
|
||||
), nil, &CMakeHelper{
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
|
||||
{"CMAKE_C_FLAGS", "-fPIC"},
|
||||
{"ZLIB_BUILD_TESTING", "ON"},
|
||||
{"ZLIB_BUILD_SHARED", "ON"},
|
||||
|
||||
@@ -19,9 +19,6 @@ func (t Toolchain) newZstd() (pkg.Artifact, string) {
|
||||
Chmod: true,
|
||||
}, &CMakeHelper{
|
||||
Append: []string{"build", "cmake"},
|
||||
Cache: []KV{
|
||||
{"CMAKE_BUILD_TYPE", "Release"},
|
||||
},
|
||||
Test: `
|
||||
make -C /usr/src/zstd/tests datagen
|
||||
ZSTD_BIN=/cure/programs/zstd /usr/src/zstd/tests/playTests.sh
|
||||
|
||||
3
make.sh
Executable file
3
make.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
HAKUREI_DIST_MAKE=1 exec "$(dirname -- "$0")/cmd/dist/dist.sh"
|
||||
@@ -35,7 +35,7 @@ package
|
||||
|
||||
|
||||
*Default:*
|
||||
` <derivation hakurei-static-x86_64-unknown-linux-musl-0.4.0> `
|
||||
` <derivation hakurei-static-x86_64-unknown-linux-musl-0.4.2> `
|
||||
|
||||
|
||||
|
||||
@@ -842,7 +842,7 @@ package
|
||||
|
||||
|
||||
*Default:*
|
||||
` <derivation hakurei-hsu-0.4.0> `
|
||||
` <derivation hakurei-hsu-0.4.2> `
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
buildGo126Module rec {
|
||||
pname = "hakurei";
|
||||
version = "0.4.0";
|
||||
version = "0.4.2";
|
||||
|
||||
srcFiltered = builtins.path {
|
||||
name = "${pname}-src";
|
||||
|
||||
@@ -237,8 +237,8 @@ in
|
||||
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||
(ent "/var/tmp" "/var/tmp" "rw,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent "/var/cache" "/var/cache" "rw,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent "/" "/.hakurei/.ro-store" "rw,relatime" "overlay" "overlay" "ro,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,redirect_dir=nofollow,userxattr")
|
||||
(ent "/" "/.hakurei/store" "rw,relatime" "overlay" "overlay" "rw,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,upperdir=/host/tmp/.hakurei-store-rw/upper,workdir=/host/tmp/.hakurei-store-rw/work,redirect_dir=nofollow,userxattr")
|
||||
(ent "/" "/.hakurei/.ro-store" "rw,relatime" "overlay" "overlay" "ro,lowerdir+=/host/nix/.ro-store,lowerdir+=/host/nix/.rw-store/upper,redirect_dir=nofollow,userxattr")
|
||||
(ent "/" "/.hakurei/store" "rw,relatime" "overlay" "overlay" "rw,lowerdir+=/host/nix/.ro-store,lowerdir+=/host/nix/.rw-store/upper,upperdir=/host/tmp/.hakurei-store-rw/upper,workdir=/host/tmp/.hakurei-store-rw/work,redirect_dir=nofollow,userxattr")
|
||||
(ent "/etc" ignore "ro,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent "/var/lib/hakurei/u0/a4" "/var/lib/hakurei/u0/a4" "rw,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent ignore "/run/user/65534/pulse/native" "ro,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
|
||||
@@ -264,8 +264,8 @@ in
|
||||
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||
(ent "/var/tmp" "/var/tmp" "rw,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent "/var/cache" "/var/cache" "rw,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent "/" "/.hakurei/.ro-store" "rw,relatime" "overlay" "overlay" "ro,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,redirect_dir=nofollow,userxattr")
|
||||
(ent "/" "/.hakurei/store" "rw,relatime" "overlay" "overlay" "rw,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,upperdir=/host/tmp/.hakurei-store-rw/upper,workdir=/host/tmp/.hakurei-store-rw/work,redirect_dir=nofollow,userxattr")
|
||||
(ent "/" "/.hakurei/.ro-store" "rw,relatime" "overlay" "overlay" "ro,lowerdir+=/host/nix/.ro-store,lowerdir+=/host/nix/.rw-store/upper,redirect_dir=nofollow,userxattr")
|
||||
(ent "/" "/.hakurei/store" "rw,relatime" "overlay" "overlay" "rw,lowerdir+=/host/nix/.ro-store,lowerdir+=/host/nix/.rw-store/upper,upperdir=/host/tmp/.hakurei-store-rw/upper,workdir=/host/tmp/.hakurei-store-rw/work,redirect_dir=nofollow,userxattr")
|
||||
(ent "/etc" ignore "ro,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent "/var/lib/hakurei/u0/a3" "/var/lib/hakurei/u0/a3" "rw,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent ignore "/run/user/1000/pulse/native" "ro,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
|
||||
@@ -270,8 +270,8 @@ in
|
||||
(ent "/dri" "/dev/dri" "rw,nosuid" "devtmpfs" "devtmpfs" ignore)
|
||||
(ent "/var/tmp" "/var/tmp" "rw,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent "/var/cache" "/var/cache" "rw,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent "/" "/.hakurei/.ro-store" "rw,relatime" "overlay" "overlay" "ro,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,redirect_dir=nofollow,userxattr")
|
||||
(ent "/" "/.hakurei/store" "rw,relatime" "overlay" "overlay" "rw,lowerdir=/host/nix/.ro-store:/host/nix/.rw-store/upper,upperdir=/host/tmp/.hakurei-store-rw/upper,workdir=/host/tmp/.hakurei-store-rw/work,redirect_dir=nofollow,uuid=on,userxattr")
|
||||
(ent "/" "/.hakurei/.ro-store" "rw,relatime" "overlay" "overlay" "ro,lowerdir+=/host/nix/.ro-store,lowerdir+=/host/nix/.rw-store/upper,redirect_dir=nofollow,userxattr")
|
||||
(ent "/" "/.hakurei/store" "rw,relatime" "overlay" "overlay" "rw,lowerdir+=/host/nix/.ro-store,lowerdir+=/host/nix/.rw-store/upper,upperdir=/host/tmp/.hakurei-store-rw/upper,workdir=/host/tmp/.hakurei-store-rw/work,redirect_dir=nofollow,uuid=on,userxattr")
|
||||
(ent "/etc" ignore "ro,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent "/var/lib/hakurei/u0/a2" "/var/lib/hakurei/u0/a2" "rw,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
(ent ignore "/run/user/65534/pulse/native" "ro,nosuid,nodev,relatime" "ext4" "/dev/vda" "rw")
|
||||
|
||||
Reference in New Issue
Block a user