aboutsummaryrefslogtreecommitdiffhomepage
path: root/cmd/hpkg
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/hpkg')
-rw-r--r--cmd/hpkg/app.go49
-rw-r--r--cmd/hpkg/main.go56
-rw-r--r--cmd/hpkg/paths.go82
-rw-r--r--cmd/hpkg/with.go51
4 files changed, 129 insertions, 109 deletions
diff --git a/cmd/hpkg/app.go b/cmd/hpkg/app.go
index fb784d73..705b393b 100644
--- a/cmd/hpkg/app.go
+++ b/cmd/hpkg/app.go
@@ -4,7 +4,6 @@ import (
"encoding/json"
"log"
"os"
- "path"
"hakurei.app/container"
"hakurei.app/container/seccomp"
@@ -56,18 +55,18 @@ type appInfo struct {
// store path to nixGL source
NixGL string `json:"nix_gl,omitempty"`
// store path to activate-and-exec script
- Launcher string `json:"launcher"`
+ Launcher *container.Absolute `json:"launcher"`
// store path to /run/current-system
- CurrentSystem string `json:"current_system"`
+ CurrentSystem *container.Absolute `json:"current_system"`
// store path to home-manager activation package
ActivationPackage string `json:"activation_package"`
}
-func (app *appInfo) toFst(pathSet *appPathSet, argv []string, flagDropShell bool) *hst.Config {
+func (app *appInfo) toHst(pathSet *appPathSet, pathname *container.Absolute, argv []string, flagDropShell bool) *hst.Config {
config := &hst.Config{
ID: app.ID,
- Path: argv[0],
+ Path: pathname,
Args: argv,
Enablements: app.Enablements,
@@ -77,9 +76,9 @@ func (app *appInfo) toFst(pathSet *appPathSet, argv []string, flagDropShell bool
DirectWayland: app.DirectWayland,
Username: "hakurei",
- Shell: shellPath,
+ Shell: pathShell,
Data: pathSet.homeDir,
- Dir: path.Join("/data/data", app.ID),
+ Dir: pathDataData.Append(app.ID),
Identity: app.Identity,
Groups: app.Groups,
@@ -92,22 +91,22 @@ func (app *appInfo) toFst(pathSet *appPathSet, argv []string, flagDropShell bool
Device: app.Device,
Tty: app.Tty || flagDropShell,
MapRealUID: app.MapRealUID,
- Filesystem: []*hst.FilesystemConfig{
- {Src: path.Join(pathSet.nixPath, "store"), Dst: "/nix/store", Must: true},
- {Src: pathSet.metaPath, Dst: path.Join(hst.Tmp, "app"), Must: true},
- {Src: container.FHSEtc + "resolv.conf"},
- {Src: container.FHSSys + "block"},
- {Src: container.FHSSys + "bus"},
- {Src: container.FHSSys + "class"},
- {Src: container.FHSSys + "dev"},
- {Src: container.FHSSys + "devices"},
+ Filesystem: []hst.FilesystemConfig{
+ {Src: pathSet.nixPath.Append("store"), Dst: pathNixStore, Must: true},
+ {Src: pathSet.metaPath, Dst: hst.AbsTmp.Append("app"), Must: true},
+ {Src: container.AbsFHSEtc.Append("resolv.conf")},
+ {Src: container.AbsFHSSys.Append("block")},
+ {Src: container.AbsFHSSys.Append("bus")},
+ {Src: container.AbsFHSSys.Append("class")},
+ {Src: container.AbsFHSSys.Append("dev")},
+ {Src: container.AbsFHSSys.Append("devices")},
},
- Link: [][2]string{
- {app.CurrentSystem, container.FHSRun + "current-system"},
- {container.FHSRun + "current-system/sw/bin", "/bin"},
- {container.FHSRun + "current-system/sw/bin", container.FHSUsrBin},
+ Link: []hst.LinkConfig{
+ {pathCurrentSystem, app.CurrentSystem.String()},
+ {pathBin, pathSwBin.String()},
+ {container.AbsFHSUsrBin, pathSwBin.String()},
},
- Etc: path.Join(pathSet.cacheDir, "etc"),
+ Etc: pathSet.cacheDir.Append("etc"),
AutoEtc: true,
},
ExtraPerms: []*hst.ExtraPermConfig{
@@ -141,6 +140,14 @@ func loadAppInfo(name string, beforeFail func()) *appInfo {
beforeFail()
log.Fatal("application identifier must not be empty")
}
+ if bundle.Launcher == nil {
+ beforeFail()
+ log.Fatal("launcher must not be empty")
+ }
+ if bundle.CurrentSystem == nil {
+ beforeFail()
+ log.Fatal("current-system must not be empty")
+ }
return bundle
}
diff --git a/cmd/hpkg/main.go b/cmd/hpkg/main.go
index 728ee14e..b8d63045 100644
--- a/cmd/hpkg/main.go
+++ b/cmd/hpkg/main.go
@@ -17,15 +17,13 @@ import (
"hakurei.app/internal/hlog"
)
-const shellPath = "/run/current-system/sw/bin/bash"
-
var (
errSuccess = errors.New("success")
)
func init() {
hlog.Prepare("hpkg")
- if err := os.Setenv("SHELL", shellPath); err != nil {
+ if err := os.Setenv("SHELL", pathShell.String()); err != nil {
log.Fatalf("cannot set $SHELL: %v", err)
}
}
@@ -82,31 +80,32 @@ func main() {
Extract package and set up for cleanup.
*/
- var workDir string
+ var workDir *container.Absolute
if p, err := os.MkdirTemp("", "hpkg.*"); err != nil {
log.Printf("cannot create temporary directory: %v", err)
return err
- } else {
- workDir = p
+ } else if workDir, err = container.NewAbs(p); err != nil {
+ log.Printf("invalid temporary directory: %v", err)
+ return err
}
cleanup := func() {
// should be faster than a native implementation
- mustRun(chmod, "-R", "+w", workDir)
- mustRun(rm, "-rf", workDir)
+ mustRun(chmod, "-R", "+w", workDir.String())
+ mustRun(rm, "-rf", workDir.String())
}
beforeRunFail.Store(&cleanup)
- mustRun(tar, "-C", workDir, "-xf", pkgPath)
+ mustRun(tar, "-C", workDir.String(), "-xf", pkgPath)
/*
Parse bundle and app metadata, do pre-install checks.
*/
- bundle := loadAppInfo(path.Join(workDir, "bundle.json"), cleanup)
+ bundle := loadAppInfo(path.Join(workDir.String(), "bundle.json"), cleanup)
pathSet := pathSetByApp(bundle.ID)
a := bundle
- if s, err := os.Stat(pathSet.metaPath); err != nil {
+ if s, err := os.Stat(pathSet.metaPath.String()); err != nil {
if !os.IsNotExist(err) {
cleanup()
log.Printf("cannot access %q: %v", pathSet.metaPath, err)
@@ -118,7 +117,7 @@ func main() {
log.Printf("metadata path %q is not a file", pathSet.metaPath)
return syscall.EBADMSG
} else {
- a = loadAppInfo(pathSet.metaPath, cleanup)
+ a = loadAppInfo(pathSet.metaPath.String(), cleanup)
if a.ID != bundle.ID {
cleanup()
log.Printf("app %q claims to have identifier %q",
@@ -209,7 +208,7 @@ func main() {
*/
// serialise metadata to ensure consistency
- if f, err := os.OpenFile(pathSet.metaPath+"~", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644); err != nil {
+ if f, err := os.OpenFile(pathSet.metaPath.String()+"~", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644); err != nil {
cleanup()
log.Printf("cannot create metadata file: %v", err)
return err
@@ -222,7 +221,7 @@ func main() {
// not fatal
}
- if err := os.Rename(pathSet.metaPath+"~", pathSet.metaPath); err != nil {
+ if err := os.Rename(pathSet.metaPath.String()+"~", pathSet.metaPath.String()); err != nil {
cleanup()
log.Printf("cannot rename metadata file: %v", err)
return err
@@ -251,7 +250,7 @@ func main() {
id := args[0]
pathSet := pathSetByApp(id)
- a := loadAppInfo(pathSet.metaPath, func() {})
+ a := loadAppInfo(pathSet.metaPath.String(), func() {})
if a.ID != id {
log.Printf("app %q claims to have identifier %q", id, a.ID)
return syscall.EBADE
@@ -275,13 +274,13 @@ func main() {
"--override-input nixpkgs path:/etc/nixpkgs " +
"path:" + a.NixGL + "#nixVulkanNvidia",
}, true, func(config *hst.Config) *hst.Config {
- config.Container.Filesystem = append(config.Container.Filesystem, []*hst.FilesystemConfig{
- {Src: container.FHSEtc + "resolv.conf"},
- {Src: container.FHSSys + "block"},
- {Src: container.FHSSys + "bus"},
- {Src: container.FHSSys + "class"},
- {Src: container.FHSSys + "dev"},
- {Src: container.FHSSys + "devices"},
+ config.Container.Filesystem = append(config.Container.Filesystem, []hst.FilesystemConfig{
+ {Src: container.AbsFHSEtc.Append("resolv.conf")},
+ {Src: container.AbsFHSSys.Append("block")},
+ {Src: container.AbsFHSSys.Append("bus")},
+ {Src: container.AbsFHSSys.Append("class")},
+ {Src: container.AbsFHSSys.Append("dev")},
+ {Src: container.AbsFHSSys.Append("devices")},
}...)
appendGPUFilesystem(config)
return config
@@ -292,15 +291,16 @@ func main() {
Create app configuration.
*/
+ pathname := a.Launcher
argv := make([]string, 1, len(args))
- if !flagDropShell {
- argv[0] = a.Launcher
+ if flagDropShell {
+ pathname = pathShell
+ argv[0] = bash
} else {
- argv[0] = shellPath
+ argv[0] = a.Launcher.String()
}
argv = append(argv, args[1:]...)
-
- config := a.toFst(pathSet, argv, flagDropShell)
+ config := a.toHst(pathSet, pathname, argv, flagDropShell)
/*
Expose GPU devices.
@@ -308,7 +308,7 @@ func main() {
if a.GPU {
config.Container.Filesystem = append(config.Container.Filesystem,
- &hst.FilesystemConfig{Src: path.Join(pathSet.nixPath, ".nixGL"), Dst: path.Join(hst.Tmp, "nixGL")})
+ hst.FilesystemConfig{Src: pathSet.nixPath.Append(".nixGL"), Dst: hst.AbsTmp.Append("nixGL")})
appendGPUFilesystem(config)
}
diff --git a/cmd/hpkg/paths.go b/cmd/hpkg/paths.go
index b7cc926a..095c24e5 100644
--- a/cmd/hpkg/paths.go
+++ b/cmd/hpkg/paths.go
@@ -4,7 +4,6 @@ import (
"log"
"os"
"os/exec"
- "path"
"strconv"
"sync/atomic"
@@ -13,19 +12,34 @@ import (
"hakurei.app/internal/hlog"
)
+const bash = "bash"
+
var (
- dataHome string
+ dataHome *container.Absolute
)
func init() {
// dataHome
- if p, ok := os.LookupEnv("HAKUREI_DATA_HOME"); ok {
- dataHome = p
+ if a, err := container.NewAbs(os.Getenv("HAKUREI_DATA_HOME")); err == nil {
+ dataHome = a
} else {
- dataHome = container.FHSVarLib + "hakurei/" + strconv.Itoa(os.Getuid())
+ dataHome = container.AbsFHSVarLib.Append("hakurei/" + strconv.Itoa(os.Getuid()))
}
}
+var (
+ pathBin = container.AbsFHSRoot.Append("bin")
+
+ pathNix = container.MustAbs("/nix/")
+ pathNixStore = pathNix.Append("store/")
+ pathCurrentSystem = container.AbsFHSRun.Append("current-system")
+ pathSwBin = pathCurrentSystem.Append("sw/bin/")
+ pathShell = pathSwBin.Append(bash)
+
+ pathData = container.MustAbs("/data")
+ pathDataData = pathData.Append("data")
+)
+
func lookPath(file string) string {
if p, err := exec.LookPath(file); err != nil {
log.Fatalf("%s: command not found", file)
@@ -51,52 +65,52 @@ func mustRun(name string, arg ...string) {
type appPathSet struct {
// ${dataHome}/${id}
- baseDir string
+ baseDir *container.Absolute
// ${baseDir}/app
- metaPath string
+ metaPath *container.Absolute
// ${baseDir}/files
- homeDir string
+ homeDir *container.Absolute
// ${baseDir}/cache
- cacheDir string
+ cacheDir *container.Absolute
// ${baseDir}/cache/nix
- nixPath string
+ nixPath *container.Absolute
}
func pathSetByApp(id string) *appPathSet {
pathSet := new(appPathSet)
- pathSet.baseDir = path.Join(dataHome, id)
- pathSet.metaPath = path.Join(pathSet.baseDir, "app")
- pathSet.homeDir = path.Join(pathSet.baseDir, "files")
- pathSet.cacheDir = path.Join(pathSet.baseDir, "cache")
- pathSet.nixPath = path.Join(pathSet.cacheDir, "nix")
+ pathSet.baseDir = dataHome.Append(id)
+ pathSet.metaPath = pathSet.baseDir.Append("app")
+ pathSet.homeDir = pathSet.baseDir.Append("files")
+ pathSet.cacheDir = pathSet.baseDir.Append("cache")
+ pathSet.nixPath = pathSet.cacheDir.Append("nix")
return pathSet
}
func appendGPUFilesystem(config *hst.Config) {
- config.Container.Filesystem = append(config.Container.Filesystem, []*hst.FilesystemConfig{
+ config.Container.Filesystem = append(config.Container.Filesystem, []hst.FilesystemConfig{
// flatpak commit 763a686d874dd668f0236f911de00b80766ffe79
- {Src: "/dev/dri", Device: true},
+ {Src: container.AbsFHSDev.Append("dri"), Device: true},
// mali
- {Src: "/dev/mali", Device: true},
- {Src: "/dev/mali0", Device: true},
- {Src: "/dev/umplock", Device: true},
+ {Src: container.AbsFHSDev.Append("mali"), Device: true},
+ {Src: container.AbsFHSDev.Append("mali0"), Device: true},
+ {Src: container.AbsFHSDev.Append("umplock"), Device: true},
// nvidia
- {Src: "/dev/nvidiactl", Device: true},
- {Src: "/dev/nvidia-modeset", Device: true},
+ {Src: container.AbsFHSDev.Append("nvidiactl"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia-modeset"), Device: true},
// nvidia OpenCL/CUDA
- {Src: "/dev/nvidia-uvm", Device: true},
- {Src: "/dev/nvidia-uvm-tools", Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia-uvm"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia-uvm-tools"), Device: true},
// flatpak commit d2dff2875bb3b7e2cd92d8204088d743fd07f3ff
- {Src: "/dev/nvidia0", Device: true}, {Src: "/dev/nvidia1", Device: true},
- {Src: "/dev/nvidia2", Device: true}, {Src: "/dev/nvidia3", Device: true},
- {Src: "/dev/nvidia4", Device: true}, {Src: "/dev/nvidia5", Device: true},
- {Src: "/dev/nvidia6", Device: true}, {Src: "/dev/nvidia7", Device: true},
- {Src: "/dev/nvidia8", Device: true}, {Src: "/dev/nvidia9", Device: true},
- {Src: "/dev/nvidia10", Device: true}, {Src: "/dev/nvidia11", Device: true},
- {Src: "/dev/nvidia12", Device: true}, {Src: "/dev/nvidia13", Device: true},
- {Src: "/dev/nvidia14", Device: true}, {Src: "/dev/nvidia15", Device: true},
- {Src: "/dev/nvidia16", Device: true}, {Src: "/dev/nvidia17", Device: true},
- {Src: "/dev/nvidia18", Device: true}, {Src: "/dev/nvidia19", Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia0"), Device: true}, {Src: container.AbsFHSDev.Append("nvidia1"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia2"), Device: true}, {Src: container.AbsFHSDev.Append("nvidia3"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia4"), Device: true}, {Src: container.AbsFHSDev.Append("nvidia5"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia6"), Device: true}, {Src: container.AbsFHSDev.Append("nvidia7"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia8"), Device: true}, {Src: container.AbsFHSDev.Append("nvidia9"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia10"), Device: true}, {Src: container.AbsFHSDev.Append("nvidia11"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia12"), Device: true}, {Src: container.AbsFHSDev.Append("nvidia13"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia14"), Device: true}, {Src: container.AbsFHSDev.Append("nvidia15"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia16"), Device: true}, {Src: container.AbsFHSDev.Append("nvidia17"), Device: true},
+ {Src: container.AbsFHSDev.Append("nvidia18"), Device: true}, {Src: container.AbsFHSDev.Append("nvidia19"), Device: true},
}...)
}
diff --git a/cmd/hpkg/with.go b/cmd/hpkg/with.go
index 444b4e7e..72ca2457 100644
--- a/cmd/hpkg/with.go
+++ b/cmd/hpkg/with.go
@@ -2,7 +2,6 @@ package main
import (
"context"
- "path"
"strings"
"hakurei.app/container"
@@ -19,8 +18,8 @@ func withNixDaemon(
mustRunAppDropShell(ctx, updateConfig(&hst.Config{
ID: app.ID,
- Path: shellPath,
- Args: []string{shellPath, "-lc", "rm -f /nix/var/nix/daemon-socket/socket && " +
+ Path: pathShell,
+ Args: []string{bash, "-lc", "rm -f /nix/var/nix/daemon-socket/socket && " +
// start nix-daemon
"nix-daemon --store / & " +
// wait for socket to appear
@@ -33,9 +32,9 @@ func withNixDaemon(
},
Username: "hakurei",
- Shell: shellPath,
+ Shell: pathShell,
Data: pathSet.homeDir,
- Dir: path.Join("/data/data", app.ID),
+ Dir: pathDataData.Append(app.ID),
ExtraPerms: []*hst.ExtraPermConfig{
{Path: dataHome, Execute: true},
{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
@@ -49,15 +48,15 @@ func withNixDaemon(
Net: net,
SeccompFlags: seccomp.AllowMultiarch,
Tty: dropShell,
- Filesystem: []*hst.FilesystemConfig{
- {Src: pathSet.nixPath, Dst: "/nix", Write: true, Must: true},
+ Filesystem: []hst.FilesystemConfig{
+ {Src: pathSet.nixPath, Dst: pathNix, Write: true, Must: true},
},
- Link: [][2]string{
- {app.CurrentSystem, container.FHSRun + "current-system"},
- {container.FHSRun + "current-system/sw/bin", "/bin"},
- {container.FHSRun + "current-system/sw/bin", container.FHSUsrBin},
+ Link: []hst.LinkConfig{
+ {pathCurrentSystem, app.CurrentSystem.String()},
+ {pathBin, pathSwBin.String()},
+ {container.AbsFHSUsrBin, pathSwBin.String()},
},
- Etc: path.Join(pathSet.cacheDir, "etc"),
+ Etc: pathSet.cacheDir.Append("etc"),
AutoEtc: true,
},
}), dropShell, beforeFail)
@@ -65,18 +64,18 @@ func withNixDaemon(
func withCacheDir(
ctx context.Context,
- action string, command []string, workDir string,
+ action string, command []string, workDir *container.Absolute,
app *appInfo, pathSet *appPathSet, dropShell bool, beforeFail func()) {
mustRunAppDropShell(ctx, &hst.Config{
ID: app.ID,
- Path: shellPath,
- Args: []string{shellPath, "-lc", strings.Join(command, " && ")},
+ Path: pathShell,
+ Args: []string{bash, "-lc", strings.Join(command, " && ")},
Username: "nixos",
- Shell: shellPath,
+ Shell: pathShell,
Data: pathSet.cacheDir, // this also ensures cacheDir via shim
- Dir: path.Join("/data/data", app.ID, "cache"),
+ Dir: pathDataData.Append(app.ID, "cache"),
ExtraPerms: []*hst.ExtraPermConfig{
{Path: dataHome, Execute: true},
{Ensure: true, Path: pathSet.baseDir, Read: true, Write: true, Execute: true},
@@ -89,16 +88,16 @@ func withCacheDir(
Hostname: formatHostname(app.Name) + "-" + action,
SeccompFlags: seccomp.AllowMultiarch,
Tty: dropShell,
- Filesystem: []*hst.FilesystemConfig{
- {Src: path.Join(workDir, "nix"), Dst: "/nix", Must: true},
- {Src: workDir, Dst: path.Join(hst.Tmp, "bundle"), Must: true},
+ Filesystem: []hst.FilesystemConfig{
+ {Src: workDir.Append("nix"), Dst: pathNix, Must: true},
+ {Src: workDir, Dst: hst.AbsTmp.Append("bundle"), Must: true},
},
- Link: [][2]string{
- {app.CurrentSystem, container.FHSRun + "current-system"},
- {container.FHSRun + "current-system/sw/bin", "/bin"},
- {container.FHSRun + "current-system/sw/bin", container.FHSUsrBin},
+ Link: []hst.LinkConfig{
+ {pathCurrentSystem, app.CurrentSystem.String()},
+ {pathBin, pathSwBin.String()},
+ {container.AbsFHSUsrBin, pathSwBin.String()},
},
- Etc: path.Join(workDir, container.FHSEtc),
+ Etc: workDir.Append(container.FHSEtc),
AutoEtc: true,
},
}, dropShell, beforeFail)
@@ -106,7 +105,7 @@ func withCacheDir(
func mustRunAppDropShell(ctx context.Context, config *hst.Config, dropShell bool, beforeFail func()) {
if dropShell {
- config.Args = []string{shellPath, "-l"}
+ config.Args = []string{bash, "-l"}
mustRunApp(ctx, config, beforeFail)
beforeFail()
internal.Exit(0)