diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-02-23 23:23:54 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-02-23 23:25:12 +0900 |
| commit | e6cd2bb2a8098d555f11034fa912158c469e6138 (patch) | |
| tree | fdb34784fdbebf870bc06f0d6456c08fa299c00f /cmd/fpkg/install.go | |
| parent | 0fb72e5d99226a1c67536f926ee2aeba25ca0fdd (diff) | |
cmd/fpkg: integrate command handler
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'cmd/fpkg/install.go')
| -rw-r--r-- | cmd/fpkg/install.go | 191 |
1 files changed, 0 insertions, 191 deletions
diff --git a/cmd/fpkg/install.go b/cmd/fpkg/install.go deleted file mode 100644 index d1643b40..00000000 --- a/cmd/fpkg/install.go +++ /dev/null @@ -1,191 +0,0 @@ -package main - -import ( - "encoding/json" - "flag" - "log" - "os" - "path" - - "git.gensokyo.uk/security/fortify/fst" - "git.gensokyo.uk/security/fortify/internal" - "git.gensokyo.uk/security/fortify/internal/fmsg" -) - -func actionInstall(args []string) { - set := flag.NewFlagSet("install", flag.ExitOnError) - var ( - dropShellInstall bool - dropShellActivate bool - ) - set.BoolVar(&dropShellInstall, "si", false, "Drop to a shell on installation") - set.BoolVar(&dropShellActivate, "sa", false, "Drop to a shell on activation") - - // Ignore errors; set is set for ExitOnError. - _ = set.Parse(args) - - args = set.Args() - - if len(args) != 1 { - log.Fatal("invalid argument") - } - pkgPath := args[0] - if !path.IsAbs(pkgPath) { - if dir, err := os.Getwd(); err != nil { - log.Fatalf("cannot get current directory: %v", err) - } else { - pkgPath = path.Join(dir, pkgPath) - } - } - - /* - Look up paths to programs started by fpkg. - This is done here to ease error handling as cleanup is not yet required. - */ - - var ( - _ = lookPath("zstd") - tar = lookPath("tar") - chmod = lookPath("chmod") - rm = lookPath("rm") - ) - - /* - Extract package and set up for cleanup. - */ - - var workDir string - if p, err := os.MkdirTemp("", "fpkg.*"); err != nil { - log.Fatalf("cannot create temporary directory: %v", err) - } else { - workDir = p - } - cleanup := func() { - // should be faster than a native implementation - mustRun(chmod, "-R", "+w", workDir) - mustRun(rm, "-rf", workDir) - } - beforeRunFail.Store(&cleanup) - - mustRun(tar, "-C", workDir, "-xf", pkgPath) - - /* - Parse bundle and app metadata, do pre-install checks. - */ - - bundle := loadBundleInfo(path.Join(workDir, "bundle.json"), cleanup) - pathSet := pathSetByApp(bundle.ID) - - app := bundle - if s, err := os.Stat(pathSet.metaPath); err != nil { - if !os.IsNotExist(err) { - cleanup() - log.Fatalf("cannot access %q: %v", pathSet.metaPath, err) - } - // did not modify app, clean installation condition met later - } else if s.IsDir() { - cleanup() - log.Fatalf("metadata path %q is not a file", pathSet.metaPath) - } else { - app = loadBundleInfo(pathSet.metaPath, cleanup) - if app.ID != bundle.ID { - cleanup() - log.Fatalf("app %q claims to have identifier %q", bundle.ID, app.ID) - } - // sec: should verify credentials - } - - if app != bundle { - // do not try to re-install - if app.NixGL == bundle.NixGL && - app.CurrentSystem == bundle.CurrentSystem && - app.Launcher == bundle.Launcher && - app.ActivationPackage == bundle.ActivationPackage { - cleanup() - log.Printf("package %q is identical to local application %q", pkgPath, app.ID) - internal.Exit(0) - } - - // AppID determines uid - if app.AppID != bundle.AppID { - cleanup() - log.Fatalf("package %q app id %d differs from installed %d", pkgPath, bundle.AppID, app.AppID) - } - - // sec: should compare version string - fmsg.Verbosef("installing application %q version %q over local %q", bundle.ID, bundle.Version, app.Version) - } else { - fmsg.Verbosef("application %q clean installation", bundle.ID) - // sec: should install credentials - } - - /* - Setup steps for files owned by the target user. - */ - - withCacheDir("install", []string{ - // export inner bundle path in the environment - "export BUNDLE=" + fst.Tmp + "/bundle", - // replace inner /etc - "mkdir -p etc", - "chmod -R +w etc", - "rm -rf etc", - "cp -dRf $BUNDLE/etc etc", - // replace inner /nix - "mkdir -p nix", - "chmod -R +w nix", - "rm -rf nix", - "cp -dRf /nix nix", - // copy from binary cache - "nix copy --offline --no-check-sigs --all --from file://$BUNDLE/res --to $PWD", - // deduplicate nix store - "nix store --offline --store $PWD optimise", - // make cache directory world-readable for autoetc - "chmod 0755 .", - }, workDir, bundle, pathSet, dropShellInstall, cleanup) - - if bundle.GPU { - withCacheDir("mesa-wrappers", []string{ - // link nixGL mesa wrappers - "mkdir -p nix/.nixGL", - "ln -s " + bundle.Mesa + "/bin/nixGLIntel nix/.nixGL/nixGL", - "ln -s " + bundle.Mesa + "/bin/nixVulkanIntel nix/.nixGL/nixVulkan", - }, workDir, bundle, pathSet, false, cleanup) - } - - /* - Activate home-manager generation. - */ - - withNixDaemon("activate", []string{ - // clean up broken links - "mkdir -p .local/state/{nix,home-manager}", - "chmod -R +w .local/state/{nix,home-manager}", - "rm -rf .local/state/{nix,home-manager}", - // run activation script - bundle.ActivationPackage + "/activate", - }, false, func(config *fst.Config) *fst.Config { return config }, bundle, pathSet, dropShellActivate, cleanup) - - /* - Installation complete. Write metadata to block re-installs or downgrades. - */ - - // serialise metadata to ensure consistency - if f, err := os.OpenFile(pathSet.metaPath+"~", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644); err != nil { - cleanup() - log.Fatalf("cannot create metadata file: %v", err) - } else if err = json.NewEncoder(f).Encode(bundle); err != nil { - cleanup() - log.Fatalf("cannot write metadata: %v", err) - } else if err = f.Close(); err != nil { - log.Printf("cannot close metadata file: %v", err) - // not fatal - } - - if err := os.Rename(pathSet.metaPath+"~", pathSet.metaPath); err != nil { - cleanup() - log.Fatalf("cannot rename metadata file: %v", err) - } - - cleanup() -} |
