diff options
Diffstat (limited to 'installpkg.go')
-rw-r--r-- | installpkg.go | 88 |
1 files changed, 63 insertions, 25 deletions
diff --git a/installpkg.go b/installpkg.go index 7354ff0..7e10e61 100644 --- a/installpkg.go +++ b/installpkg.go @@ -1,12 +1,14 @@ package pkgtools import ( + "archive/tar" "fmt" "io" "os" "os/exec" "path" "path/filepath" + "strings" "time" "github.com/juju/fslock" @@ -99,7 +101,12 @@ func (s *InstallPkgFlags) SetEnvValues() { } } -func runInstallScript(flags *InstallPkgFlags) error { +func runInstallScript(flags *InstallPkgFlags, installPath string) error { + installPath, err := filepath.Abs(installPath) + if err != nil { + return err + } + l := fslock.New(FileLockPath(flags.LockDir, filepath.Base(PackageInstallScript))) if err := l.Lock(); err != nil { return err @@ -116,7 +123,7 @@ func runInstallScript(flags *InstallPkgFlags) error { } defer os.Chdir(cwd) - installScript := path.Join(flags.Root, PackageInstallScript) + installScript := path.Join(installPath, filepath.Base(PackageInstallScript)) if _, err := os.Stat(installScript); !os.IsNotExist(err) { cmd := exec.Command("/bin/bash", installScript) cmd.Stdin = os.Stdout @@ -287,19 +294,65 @@ func writeToDatabase(target string, pkg string) error { return nil } +// ExtractSlackwarePkg unarchives the slackware package into the given +// directory. The package metadata, under the archives '/install' path, is put +// into a temporary directory and returned. +func ExtractSlackwarePkg(flags *InstallPkgFlags, fp string) (string, error) { + slackPkg, err := OpenSlackwarePkg(fp) + if err != nil { + return "", errors.Wrap(err, "extracting package") + } + defer slackPkg.Close() + + toRoot := NewTarExtractor(&TarCfg{ + Root: flags.Root, + Chmod: flags.chmod, + Chown: flags.chown, + }) + + tmpDir := os.TempDir() + if _, err := os.Stat(tmpDir); os.IsNotExist(err) { + tmpDir = "/" + } else if err != nil { + return "", errors.Wrap(err, "extracting package") + } + tempInstallDir, err := os.MkdirTemp(tmpDir, "installpkg-*") + if err != nil { + return "", errors.Wrap(err, "extracting package") + } + toTempInstallDir := NewTarExtractor(&TarCfg{ + Root: tempInstallDir, + Chmod: flags.chmod, + Chown: flags.chown, + }) + + err = FilterTar( + slackPkg, + TarFilterFunc(func(h *tar.Header, r io.Reader) error { + if ok, err := IsParentDir(PackageInstallPath, h.Name); ok { + h.Name = strings.TrimPrefix(h.Name, PackageInstallPath+"/") + if h.Name == "" { + h.Name = "." + } + return toTempInstallDir.FilterTar(h, r) + } else if err != nil { + return errors.Wrap(err, "installing package") + } + + return toRoot.FilterTar(h, r) + }), + ) + return tempInstallDir, errors.Wrap(err, "installing package") +} + func InstallPkg(flags *InstallPkgFlags, pkgs ...string) error { - // Apply default flag values + // TODO: Apply default flag values err := initializeDirectories(flags) if err != nil { return err } - installPath := path.Join(flags.Root, PackageInstallPath) - if _, err := os.Stat(installPath); !errors.Is(err, os.ErrNotExist) { - return errors.Errorf("The '%s' directory exists and would be used by installpkg and removed. Please consider renaming the directory or using Slackware's installpkg.", installPath) - } - for _, pkg := range pkgs { fmt.Printf("installing %s\n", PackageBase(pkg)) err = writeToDatabase(flags.Root, pkg) @@ -307,22 +360,7 @@ func InstallPkg(flags *InstallPkgFlags, pkgs ...string) error { return errors.Wrap(err, "writing package to database") } - err = func() error { - slackPkg, err := OpenSlackwarePkg(pkg) - if err != nil { - return err - } - defer slackPkg.Close() - err = InstallArchive( - slackPkg, - &InstallArchiveCfg{ - Root: flags.Root, - Chmod: flags.chmod, - Chown: flags.chown, - }, - ) - return errors.Wrap(err, "installing package") - }() + installPath, err := ExtractSlackwarePkg(flags, pkg) if err != nil { return errors.Wrap(err, "writing package to database") } @@ -336,7 +374,7 @@ func InstallPkg(flags *InstallPkgFlags, pkgs ...string) error { _ = runLDConfig(flags.LockDir) // TODO: command should still run after failed 'install script' execution - err = runInstallScript(flags) + err = runInstallScript(flags, installPath) if err != nil { fmt.Fprintln(os.Stderr, errors.Wrap(err, "running install script")) } |