hst/fs: interface filesystem config
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m14s
Test / Hakurei (push) Successful in 3m37s
Test / Hpkg (push) Successful in 4m27s
Test / Sandbox (race detector) (push) Successful in 4m23s
Test / Hakurei (race detector) (push) Successful in 5m22s
Test / Flake checks (push) Successful in 1m22s
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m14s
Test / Hakurei (push) Successful in 3m37s
Test / Hpkg (push) Successful in 4m27s
Test / Sandbox (race detector) (push) Successful in 4m23s
Test / Hakurei (race detector) (push) Successful in 5m22s
Test / Flake checks (push) Successful in 1m22s
This allows mount points to be represented by different underlying structs. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -13,6 +13,9 @@ import (
|
||||
)
|
||||
|
||||
func m(pathname string) *container.Absolute { return container.MustAbs(pathname) }
|
||||
func f(c hst.FilesystemConfig) hst.FilesystemConfigJSON {
|
||||
return hst.FilesystemConfigJSON{FilesystemConfig: c}
|
||||
}
|
||||
|
||||
var testCasesNixos = []sealTestCase{
|
||||
{
|
||||
@@ -25,11 +28,18 @@ var testCasesNixos = []sealTestCase{
|
||||
|
||||
Container: &hst.ContainerConfig{
|
||||
Userns: true, Net: true, MapRealUID: true, Env: nil, AutoEtc: true,
|
||||
Filesystem: []hst.FilesystemConfig{
|
||||
{Src: m("/bin"), Must: true}, {Src: m("/usr/bin/"), Must: true},
|
||||
{Src: m("/nix/store"), Must: true}, {Src: m("/run/current-system"), Must: true},
|
||||
{Src: m("/sys/block")}, {Src: m("/sys/bus")}, {Src: m("/sys/class")}, {Src: m("/sys/dev")}, {Src: m("/sys/devices")},
|
||||
{Src: m("/run/opengl-driver"), Must: true}, {Src: m("/dev/dri"), Device: true},
|
||||
Filesystem: []hst.FilesystemConfigJSON{
|
||||
f(&hst.FSBind{Src: m("/bin")}),
|
||||
f(&hst.FSBind{Src: m("/usr/bin/")}),
|
||||
f(&hst.FSBind{Src: m("/nix/store")}),
|
||||
f(&hst.FSBind{Src: m("/run/current-system")}),
|
||||
f(&hst.FSBind{Src: m("/sys/block"), Optional: true}),
|
||||
f(&hst.FSBind{Src: m("/sys/bus"), Optional: true}),
|
||||
f(&hst.FSBind{Src: m("/sys/class"), Optional: true}),
|
||||
f(&hst.FSBind{Src: m("/sys/dev"), Optional: true}),
|
||||
f(&hst.FSBind{Src: m("/sys/devices"), Optional: true}),
|
||||
f(&hst.FSBind{Src: m("/run/opengl-driver")}),
|
||||
f(&hst.FSBind{Src: m("/dev/dri"), Device: true, Optional: true}),
|
||||
},
|
||||
},
|
||||
SystemBus: &dbus.Config{
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"io/fs"
|
||||
"maps"
|
||||
"path"
|
||||
"slices"
|
||||
"syscall"
|
||||
|
||||
"hakurei.app/container"
|
||||
@@ -126,73 +125,63 @@ func newContainer(s *hst.ContainerConfig, os sys.State, prefix string, uid, gid
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
// evaluated path, input path
|
||||
hidePathSource := make([][2]string, 0, len(s.Filesystem))
|
||||
|
||||
var hidePathSourceCount int
|
||||
for i, c := range s.Filesystem {
|
||||
if !c.Valid() {
|
||||
return nil, nil, fmt.Errorf("invalid filesystem at index %d", i)
|
||||
}
|
||||
c.Apply(params.Ops)
|
||||
|
||||
// fs counter
|
||||
hidePathSourceCount += len(c.Host())
|
||||
}
|
||||
|
||||
// AutoRoot is a collection of many BindMountOp internally
|
||||
var autoRootEntries []fs.DirEntry
|
||||
if s.AutoRoot != nil {
|
||||
if d, err := os.ReadDir(s.AutoRoot.String()); err != nil {
|
||||
return nil, nil, err
|
||||
} else {
|
||||
hidePathSource = slices.Grow(hidePathSource, len(d))
|
||||
for _, ent := range d {
|
||||
name := ent.Name()
|
||||
if container.IsAutoRootBindable(name) {
|
||||
name = path.Join(s.AutoRoot.String(), name)
|
||||
srcP := [2]string{name, name}
|
||||
if err = evalSymlinks(os, &srcP[0]); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
hidePathSource = append(hidePathSource, srcP)
|
||||
}
|
||||
// autoroot counter
|
||||
hidePathSourceCount += len(d)
|
||||
autoRootEntries = d
|
||||
}
|
||||
}
|
||||
|
||||
hidePathSource := make([]*container.Absolute, 0, hidePathSourceCount)
|
||||
|
||||
// fs append
|
||||
for _, c := range s.Filesystem {
|
||||
// all entries already checked above
|
||||
hidePathSource = append(hidePathSource, c.Host()...)
|
||||
}
|
||||
|
||||
// autoroot append
|
||||
if s.AutoRoot != nil {
|
||||
for _, ent := range autoRootEntries {
|
||||
name := ent.Name()
|
||||
if container.IsAutoRootBindable(name) {
|
||||
hidePathSource = append(hidePathSource, s.AutoRoot.Append(name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i, c := range s.Filesystem {
|
||||
if c.Src == nil {
|
||||
return nil, nil, fmt.Errorf("invalid filesystem at index %d", i)
|
||||
// evaluated path, input path
|
||||
hidePathSourceEval := make([][2]string, len(hidePathSource))
|
||||
for i, a := range hidePathSource {
|
||||
if a == nil {
|
||||
// unreachable
|
||||
return nil, nil, syscall.ENOTRECOVERABLE
|
||||
}
|
||||
|
||||
// special filesystems
|
||||
switch c.Src.String() {
|
||||
case container.Nonexistent:
|
||||
if c.Dst == nil {
|
||||
return nil, nil, errors.New("tmpfs dst must not be nil")
|
||||
}
|
||||
if c.Write {
|
||||
params.Tmpfs(c.Dst, hst.TmpfsSize, hst.TmpfsPerm)
|
||||
} else {
|
||||
params.Readonly(c.Dst, hst.TmpfsPerm)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
dst := c.Dst
|
||||
if dst == nil {
|
||||
dst = c.Src
|
||||
}
|
||||
|
||||
p := [2]string{c.Src.String(), c.Src.String()}
|
||||
if err := evalSymlinks(os, &p[0]); err != nil {
|
||||
hidePathSourceEval[i] = [2]string{a.String(), a.String()}
|
||||
if err := evalSymlinks(os, &hidePathSourceEval[i][0]); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
hidePathSource = append(hidePathSource, p)
|
||||
|
||||
var flags int
|
||||
if c.Write {
|
||||
flags |= container.BindWritable
|
||||
}
|
||||
if c.Device {
|
||||
flags |= container.BindDevice | container.BindWritable
|
||||
}
|
||||
if !c.Must {
|
||||
flags |= container.BindOptional
|
||||
}
|
||||
params.Bind(c.Src, dst, flags)
|
||||
}
|
||||
|
||||
for _, p := range hidePathSource {
|
||||
for _, p := range hidePathSourceEval {
|
||||
for i := range hidePaths {
|
||||
// skip matched entries
|
||||
if hidePathMatch[i] {
|
||||
|
||||
@@ -248,15 +248,15 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co
|
||||
|
||||
// bind GPU stuff
|
||||
if config.Enablements&(system.EX11|system.EWayland) != 0 {
|
||||
conf.Filesystem = append(conf.Filesystem, hst.FilesystemConfig{Src: container.AbsFHSDev.Append("dri"), Device: true})
|
||||
conf.Filesystem = append(conf.Filesystem, hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{Src: container.AbsFHSDev.Append("dri"), Device: true, Optional: true}})
|
||||
}
|
||||
// opportunistically bind kvm
|
||||
conf.Filesystem = append(conf.Filesystem, hst.FilesystemConfig{Src: container.AbsFHSDev.Append("kvm"), Device: true})
|
||||
conf.Filesystem = append(conf.Filesystem, hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSBind{Src: container.AbsFHSDev.Append("kvm"), Device: true, Optional: true}})
|
||||
|
||||
// hide nscd from container if present
|
||||
nscd := container.AbsFHSVar.Append("run/nscd")
|
||||
if _, err := sys.Stat(nscd.String()); !errors.Is(err, fs.ErrNotExist) {
|
||||
conf.Filesystem = append(conf.Filesystem, hst.FilesystemConfig{Dst: nscd, Src: container.AbsNonexistent})
|
||||
conf.Filesystem = append(conf.Filesystem, hst.FilesystemConfigJSON{FilesystemConfig: &hst.FSEphemeral{Dst: nscd}})
|
||||
}
|
||||
|
||||
config.Container = conf
|
||||
|
||||
Reference in New Issue
Block a user