From 0e6c1a50260de141c50bb50fd3f2b2bcf9a3fe64 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Tue, 7 Oct 2025 20:06:26 +0900 Subject: container/check: move absolute pathname This allows use of absolute pathname values without importing container. Signed-off-by: Ophestra --- hst/config.go | 20 ++++++++++---------- hst/fs.go | 5 +++-- hst/fs_test.go | 23 ++++++++++++----------- hst/fsbind.go | 11 ++++++----- hst/fsephemeral.go | 8 ++++---- hst/fslink.go | 8 ++++---- hst/fsoverlay.go | 15 ++++++++------- hst/fsoverlay_test.go | 3 ++- hst/hst.go | 23 ++++++++++++----------- 9 files changed, 61 insertions(+), 55 deletions(-) (limited to 'hst') diff --git a/hst/config.go b/hst/config.go index e661d2d3..7c96874f 100644 --- a/hst/config.go +++ b/hst/config.go @@ -5,12 +5,12 @@ import ( "strconv" "time" - "hakurei.app/container" + "hakurei.app/container/check" ) const Tmp = "/.hakurei" -var AbsTmp = container.MustAbs(Tmp) +var AbsTmp = check.MustAbs(Tmp) const ( // WaitDelayDefault is used when WaitDelay has its zero value. @@ -107,12 +107,12 @@ type ( // Defaults to passwd name of target uid or chronos. Username string `json:"username,omitempty"` // Pathname of shell in the container filesystem to use for the emulated user. - Shell *container.Absolute `json:"shell"` + Shell *check.Absolute `json:"shell"` // Directory in the container filesystem to enter and use as the home directory of the emulated user. - Home *container.Absolute `json:"home"` + Home *check.Absolute `json:"home"` // Pathname to executable file in the container filesystem. - Path *container.Absolute `json:"path,omitempty"` + Path *check.Absolute `json:"path,omitempty"` // Final args passed to the initial program. Args []string `json:"args"` } @@ -161,11 +161,11 @@ func (config *Config) Validate() error { // ExtraPermConfig describes an acl update op. type ExtraPermConfig struct { - Ensure bool `json:"ensure,omitempty"` - Path *container.Absolute `json:"path"` - Read bool `json:"r,omitempty"` - Write bool `json:"w,omitempty"` - Execute bool `json:"x,omitempty"` + Ensure bool `json:"ensure,omitempty"` + Path *check.Absolute `json:"path"` + Read bool `json:"r,omitempty"` + Write bool `json:"w,omitempty"` + Execute bool `json:"x,omitempty"` } func (e *ExtraPermConfig) String() string { diff --git a/hst/fs.go b/hst/fs.go index 1d330951..4508e974 100644 --- a/hst/fs.go +++ b/hst/fs.go @@ -7,6 +7,7 @@ import ( "reflect" "hakurei.app/container" + "hakurei.app/container/check" ) // FilesystemConfig is an abstract representation of a mount point. @@ -14,9 +15,9 @@ type FilesystemConfig interface { // Valid returns whether the configuration is valid. Valid() bool // Path returns the target path in the container. - Path() *container.Absolute + Path() *check.Absolute // Host returns a slice of all host paths used by this operation. - Host() []*container.Absolute + Host() []*check.Absolute // Apply appends the [container.Op] implementing this operation. Apply(z *ApplyState) diff --git a/hst/fs_test.go b/hst/fs_test.go index 00186d20..35d58ad6 100644 --- a/hst/fs_test.go +++ b/hst/fs_test.go @@ -9,6 +9,7 @@ import ( "testing" "hakurei.app/container" + "hakurei.app/container/check" "hakurei.app/hst" ) @@ -216,11 +217,11 @@ type stubFS struct { typeName string } -func (s stubFS) Valid() bool { return false } -func (s stubFS) Path() *container.Absolute { panic("unreachable") } -func (s stubFS) Host() []*container.Absolute { panic("unreachable") } -func (s stubFS) Apply(*hst.ApplyState) { panic("unreachable") } -func (s stubFS) String() string { return "" } +func (s stubFS) Valid() bool { return false } +func (s stubFS) Path() *check.Absolute { panic("unreachable") } +func (s stubFS) Host() []*check.Absolute { panic("unreachable") } +func (s stubFS) Apply(*hst.ApplyState) { panic("unreachable") } +func (s stubFS) String() string { return "" } type sCheck struct { FS hst.FilesystemConfigJSON `json:"fs"` @@ -232,8 +233,8 @@ type fsTestCase struct { fs hst.FilesystemConfig valid bool ops container.Ops - path *container.Absolute - host []*container.Absolute + path *check.Absolute + host []*check.Absolute str string } @@ -287,11 +288,11 @@ func checkFs(t *testing.T, testCases []fsTestCase) { } } -func m(pathname string) *container.Absolute { return container.MustAbs(pathname) } -func ms(pathnames ...string) []*container.Absolute { - as := make([]*container.Absolute, len(pathnames)) +func m(pathname string) *check.Absolute { return check.MustAbs(pathname) } +func ms(pathnames ...string) []*check.Absolute { + as := make([]*check.Absolute, len(pathnames)) for i, pathname := range pathnames { - as[i] = container.MustAbs(pathname) + as[i] = check.MustAbs(pathname) } return as } diff --git a/hst/fsbind.go b/hst/fsbind.go index 3769fcd9..2cebf6b6 100644 --- a/hst/fsbind.go +++ b/hst/fsbind.go @@ -5,6 +5,7 @@ import ( "strings" "hakurei.app/container" + "hakurei.app/container/check" ) func init() { gob.Register(new(FSBind)) } @@ -15,9 +16,9 @@ const FilesystemBind = "bind" // FSBind represents a host to container bind mount. type FSBind struct { // mount point in container, same as Source if empty - Target *container.Absolute `json:"dst,omitempty"` + Target *check.Absolute `json:"dst,omitempty"` // host filesystem path to make available to the container - Source *container.Absolute `json:"src"` + Source *check.Absolute `json:"src"` // do not mount Target read-only Write bool `json:"write,omitempty"` // do not disable device files on Target, implies Write @@ -66,7 +67,7 @@ func (b *FSBind) Valid() bool { return true } -func (b *FSBind) Path() *container.Absolute { +func (b *FSBind) Path() *check.Absolute { if !b.Valid() { return nil } @@ -76,11 +77,11 @@ func (b *FSBind) Path() *container.Absolute { return b.Target } -func (b *FSBind) Host() []*container.Absolute { +func (b *FSBind) Host() []*check.Absolute { if !b.Valid() { return nil } - return []*container.Absolute{b.Source} + return []*check.Absolute{b.Source} } func (b *FSBind) Apply(z *ApplyState) { diff --git a/hst/fsephemeral.go b/hst/fsephemeral.go index e09fa8f9..631235b5 100644 --- a/hst/fsephemeral.go +++ b/hst/fsephemeral.go @@ -5,7 +5,7 @@ import ( "os" "strings" - "hakurei.app/container" + "hakurei.app/container/check" ) func init() { gob.Register(new(FSEphemeral)) } @@ -16,7 +16,7 @@ const FilesystemEphemeral = "ephemeral" // FSEphemeral represents an ephemeral container mount point. type FSEphemeral struct { // mount point in container - Target *container.Absolute `json:"dst,omitempty"` + Target *check.Absolute `json:"dst,omitempty"` // do not mount filesystem read-only Write bool `json:"write,omitempty"` // upper limit on the size of the filesystem @@ -27,14 +27,14 @@ type FSEphemeral struct { func (e *FSEphemeral) Valid() bool { return e != nil && e.Target != nil } -func (e *FSEphemeral) Path() *container.Absolute { +func (e *FSEphemeral) Path() *check.Absolute { if !e.Valid() { return nil } return e.Target } -func (e *FSEphemeral) Host() []*container.Absolute { return nil } +func (e *FSEphemeral) Host() []*check.Absolute { return nil } const fsEphemeralDefaultPerm = os.FileMode(0755) diff --git a/hst/fslink.go b/hst/fslink.go index 40b4fd8b..473506e6 100644 --- a/hst/fslink.go +++ b/hst/fslink.go @@ -4,7 +4,7 @@ import ( "encoding/gob" "path" - "hakurei.app/container" + "hakurei.app/container/check" ) func init() { gob.Register(new(FSLink)) } @@ -15,7 +15,7 @@ const FilesystemLink = "link" // FSLink represents a symlink in the container filesystem. type FSLink struct { // link path in container - Target *container.Absolute `json:"dst"` + Target *check.Absolute `json:"dst"` // linkname the symlink points to Linkname string `json:"linkname"` // whether to dereference linkname before creating the link @@ -29,14 +29,14 @@ func (l *FSLink) Valid() bool { return !l.Dereference || path.IsAbs(l.Linkname) } -func (l *FSLink) Path() *container.Absolute { +func (l *FSLink) Path() *check.Absolute { if !l.Valid() { return nil } return l.Target } -func (l *FSLink) Host() []*container.Absolute { return nil } +func (l *FSLink) Host() []*check.Absolute { return nil } func (l *FSLink) Apply(z *ApplyState) { if !l.Valid() { diff --git a/hst/fsoverlay.go b/hst/fsoverlay.go index f3c2f373..2c2a195c 100644 --- a/hst/fsoverlay.go +++ b/hst/fsoverlay.go @@ -5,6 +5,7 @@ import ( "strings" "hakurei.app/container" + "hakurei.app/container/check" ) func init() { gob.Register(new(FSOverlay)) } @@ -15,14 +16,14 @@ const FilesystemOverlay = "overlay" // FSOverlay represents an overlay mount point. type FSOverlay struct { // mount point in container - Target *container.Absolute `json:"dst"` + Target *check.Absolute `json:"dst"` // any filesystem, does not need to be on a writable filesystem, must not be nil - Lower []*container.Absolute `json:"lower"` + Lower []*check.Absolute `json:"lower"` // the upperdir is normally on a writable filesystem, leave as nil to mount Lower readonly - Upper *container.Absolute `json:"upper,omitempty"` + Upper *check.Absolute `json:"upper,omitempty"` // the workdir needs to be an empty directory on the same filesystem as Upper, must not be nil if Upper is populated - Work *container.Absolute `json:"work,omitempty"` + Work *check.Absolute `json:"work,omitempty"` } func (o *FSOverlay) Valid() bool { @@ -43,18 +44,18 @@ func (o *FSOverlay) Valid() bool { } } -func (o *FSOverlay) Path() *container.Absolute { +func (o *FSOverlay) Path() *check.Absolute { if !o.Valid() { return nil } return o.Target } -func (o *FSOverlay) Host() []*container.Absolute { +func (o *FSOverlay) Host() []*check.Absolute { if !o.Valid() { return nil } - p := make([]*container.Absolute, 0, 2+len(o.Lower)) + p := make([]*check.Absolute, 0, 2+len(o.Lower)) if o.Upper != nil && o.Work != nil { p = append(p, o.Upper, o.Work) } diff --git a/hst/fsoverlay_test.go b/hst/fsoverlay_test.go index 8a5732a3..15875bb6 100644 --- a/hst/fsoverlay_test.go +++ b/hst/fsoverlay_test.go @@ -4,13 +4,14 @@ import ( "testing" "hakurei.app/container" + "hakurei.app/container/check" "hakurei.app/hst" ) func TestFSOverlay(t *testing.T) { checkFs(t, []fsTestCase{ {"nil", (*hst.FSOverlay)(nil), false, nil, nil, nil, ""}, - {"nil lower", &hst.FSOverlay{Target: m("/etc"), Lower: []*container.Absolute{nil}}, false, nil, nil, nil, ""}, + {"nil lower", &hst.FSOverlay{Target: m("/etc"), Lower: []*check.Absolute{nil}}, false, nil, nil, nil, ""}, {"zero lower", &hst.FSOverlay{Target: m("/etc"), Upper: m("/"), Work: m("/")}, false, nil, nil, nil, ""}, {"zero lower ro", &hst.FSOverlay{Target: m("/etc")}, false, nil, nil, nil, ""}, {"short lower", &hst.FSOverlay{Target: m("/etc"), Lower: ms("/etc")}, false, nil, nil, nil, ""}, diff --git a/hst/hst.go b/hst/hst.go index 3e4c7dee..9145666f 100644 --- a/hst/hst.go +++ b/hst/hst.go @@ -7,6 +7,7 @@ import ( "os" "hakurei.app/container" + "hakurei.app/container/check" ) // An AppError is returned while starting an app according to [hst.Config]. @@ -38,13 +39,13 @@ func (e *AppError) Message() string { // Paths contains environment-dependent paths used by hakurei. type Paths struct { // temporary directory returned by [os.TempDir] (usually `/tmp`) - TempDir *container.Absolute `json:"temp_dir"` + TempDir *check.Absolute `json:"temp_dir"` // path to shared directory (usually `/tmp/hakurei.%d`, [Info.User]) - SharePath *container.Absolute `json:"share_path"` + SharePath *check.Absolute `json:"share_path"` // XDG_RUNTIME_DIR value (usually `/run/user/%d`, uid) - RuntimePath *container.Absolute `json:"runtime_path"` + RuntimePath *check.Absolute `json:"runtime_path"` // application runtime directory (usually `/run/user/%d/hakurei`) - RunDirPath *container.Absolute `json:"run_dir_path"` + RunDirPath *check.Absolute `json:"run_dir_path"` } type Info struct { @@ -115,22 +116,22 @@ func Template() *Config { {&FSBind{Target: container.AbsFHSEtc, Source: container.AbsFHSEtc, Special: true}}, {&FSEphemeral{Target: container.AbsFHSTmp, Write: true, Perm: 0755}}, {&FSOverlay{ - Target: container.MustAbs("/nix/store"), - Lower: []*container.Absolute{container.MustAbs("/mnt-root/nix/.ro-store")}, - Upper: container.MustAbs("/mnt-root/nix/.rw-store/upper"), - Work: container.MustAbs("/mnt-root/nix/.rw-store/work"), + Target: check.MustAbs("/nix/store"), + Lower: []*check.Absolute{check.MustAbs("/mnt-root/nix/.ro-store")}, + Upper: check.MustAbs("/mnt-root/nix/.rw-store/upper"), + Work: check.MustAbs("/mnt-root/nix/.rw-store/work"), }}, - {&FSBind{Source: container.MustAbs("/nix/store")}}, + {&FSBind{Source: check.MustAbs("/nix/store")}}, {&FSLink{Target: container.AbsFHSRun.Append("current-system"), Linkname: "/run/current-system", Dereference: true}}, {&FSLink{Target: container.AbsFHSRun.Append("opengl-driver"), Linkname: "/run/opengl-driver", Dereference: true}}, {&FSBind{Source: container.AbsFHSVarLib.Append("hakurei/u0/org.chromium.Chromium"), - Target: container.MustAbs("/data/data/org.chromium.Chromium"), Write: true, Ensure: true}}, + Target: check.MustAbs("/data/data/org.chromium.Chromium"), Write: true, Ensure: true}}, {&FSBind{Source: container.AbsFHSDev.Append("dri"), Device: true, Optional: true}}, }, Username: "chronos", Shell: container.AbsFHSRun.Append("current-system/sw/bin/zsh"), - Home: container.MustAbs("/data/data/org.chromium.Chromium"), + Home: check.MustAbs("/data/data/org.chromium.Chromium"), Path: container.AbsFHSRun.Append("current-system/sw/bin/chromium"), Args: []string{ -- cgit v1.3.1