aboutsummaryrefslogtreecommitdiff
path: root/pkgtools.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools.go')
-rw-r--r--pkgtools.go534
1 files changed, 0 insertions, 534 deletions
diff --git a/pkgtools.go b/pkgtools.go
deleted file mode 100644
index 5c8e928..0000000
--- a/pkgtools.go
+++ /dev/null
@@ -1,534 +0,0 @@
-package pkgtools
-
-import (
- "archive/tar"
- "bufio"
- "bytes"
- "compress/bzip2"
- "compress/gzip"
- "fmt"
- "io"
- "os"
- "path/filepath"
- "regexp"
- "strings"
-
- "github.com/pkg/errors"
- "github.com/xi2/xz"
-)
-
-const (
- // InstallLockDir is used to prevent install script collisions.
- InstallLockDir = "/run/lock/pkgtools"
-
- // PackageInstallPath is the place for special package files.
- PackageInstallPath = "install"
- PackageInstallScript = "install/doinst.sh"
- PackageUninstallScript = "install/douinst.sh"
- PackageSlackDescFile = "install/slack-desc"
-
- InstalledScriptPath = "var/lib/pkgtools/scripts"
- InstalledPackagePath = "var/lib/pkgtools/packages"
- // ADMDir is the package database directories (packages, scripts).
- ADMDir = "var/lib/pkgtools"
- // Is the removed packages/scripts log files.
- TmpDir = "var/lib/pkgtools/setup/tmp"
- LogDir = "var/log/pkgtools"
- InstalledRemovedPackagePath = "var/log/pkgtools/removed_packages"
- InstalledRemovedScriptsPath = "var/log/pkgtools/removed_scripts"
- InstalledRemovedUninstallScriptPath = "var/log/pkgtools/removed_uninstall_scripts"
-)
-
-type PackageType string
-
-const (
- UnsupportedPackageFormat = "unsupported package format"
- TGZ = "tgz"
- TBZ = "tbz"
- TLZ = "tlz"
- TXZ = "txz"
-)
-
-var SupportedPackageTypes = []string{
- TGZ,
- TBZ,
- TXZ,
-}
-
-func IsSlackwarePkg(fp string) bool {
- ext := filepath.Ext(filepath.Base(fp))
- for _, v := range SupportedPackageTypes {
- if "."+v == ext {
- return true
- }
- }
- return false
-}
-
-func FileLockPath(dir string, f string) string {
- return filepath.Join(dir, f) + ".lock"
-}
-
-func TargetPackagePath(root string, pkg string) string {
- return filepath.Join(root, InstalledPackagePath, pkg)
-}
-
-func TargetRemovedPackagePath(root string, pkg string) string {
- return filepath.Join(root, InstalledRemovedPackagePath, pkg)
-}
-
-func TargetRemovedUninstalllScriptPath(root string, pkg string) string {
- return filepath.Join(root, InstalledRemovedUninstallScriptPath, pkg)
-}
-
-func TargetTmpDir(root string) string {
- return filepath.Join(root, ADMDir, "setup", "tmp")
-}
-
-func TargetPackageInfoPath(root string, pkg string) string {
- return filepath.Join(root, InstalledPackagePath, pkg)
-}
-
-func TargetScriptPath(root string, pkg string) string {
- return filepath.Join(root, InstalledScriptPath, pkg)
-}
-
-func NewCompressedFileReader(
- r io.Reader,
- format PackageType,
-) (io.Reader, error) {
- switch format {
- case TBZ:
- dec := bzip2.NewReader(r)
- return dec, nil
- case TGZ:
- dec, err := gzip.NewReader(r)
- return dec, err
- case TXZ:
- dec, err := xz.NewReader(r, 0)
- return dec, err
- default:
- return nil, errors.New(UnsupportedPackageFormat)
- }
-}
-
-func GetFullPackageName(
- root string,
- name string,
-) (string, bool, error) {
- pkgs, err := ListPackages(root)
- if err != nil {
- return "", false, err
- }
- for _, pkg := range pkgs {
- v, err := PackageName(pkg)
- if err != nil {
- return "", false, err
- }
- if v == name {
- return pkg, true, nil
- } else if pkg == name {
- return pkg, true, nil
- }
- }
- return "", false, nil
-}
-
-func GetPackageSoftLinks(root string, pkg string) ([]string, error) {
- p := filepath.Join(root, InstalledScriptPath, pkg)
- if ok, _ := IsFile(p); !ok {
- return nil, nil
- }
- links, err := ReadPackageSoftLinks(p)
- return links, err
-}
-
-func ListPackages(
- root string,
-) ([]string, error) {
- entries, err := os.ReadDir(filepath.Join(root, InstalledPackagePath))
- if err != nil {
- return nil, err
- }
- var pkgs []string
- for _, entry := range entries {
- ok, err := IsFile(filepath.Join(root, InstalledPackagePath, entry.Name()))
- if err != nil {
- return nil, err
- }
- if ok {
- pkgs = append(pkgs, entry.Name())
- }
- }
-
- return pkgs, nil
-}
-
-// Original from Slackware's 'removepkg'
-// sed -n 's,^[ ]*( [ ]*cd[ ]* \(.*\) [ ]*; [ ]*rm [ ]*-rf[ ]* \(.*\) [ ]*)[ ]*$,\1/\2,p' </var/lib/pkgtools/scripts/acl-2.3.1-x86_64-1
-var regExpSoftLinks = regexp.MustCompile("(\\s*cd\\s*(.*)\\s*; rm -rf (.*) )")
-
-func ParsePackageSoftLinks(
- str string,
-) ([]string, error) {
- var ret []string
- matches := regExpSoftLinks.FindAllStringSubmatch(str, -1)
- for _, m := range matches {
- if len(m) != 4 {
- continue
- }
- ret = append(ret, filepath.Join(
- strings.TrimSpace(m[2]),
- strings.TrimSpace(m[3]),
- ))
- }
- return ret, nil
-}
-
-func ReadPackageSoftLinks(
- path string,
-) ([]string, error) {
- pkgScript := filepath.Join(path)
- f, err := os.Open(pkgScript)
- if err != nil {
- return nil, err
- }
- defer f.Close()
-
- buf, err := io.ReadAll(f)
- if err != nil {
- return nil, err
- }
-
- links, err := ParsePackageSoftLinks(string(buf))
- if err != nil {
- return nil, errors.Wrap(err, "getting package generated links")
- }
- return links, err
-}
-
-type SlackwarePkg struct {
- Format PackageType
- file *os.File
-
- tarR *tar.Reader
- r io.Reader
-
- uncompressedSize int64
- pkgName string
- pkgInfo PackageInfo
-}
-
-var _ TarReader = (*SlackwarePkg)(nil)
-
-func OpenSlackwarePkg(fp string) (*SlackwarePkg, error) {
- var pkg SlackwarePkg
- var err error
-
- if v := filepath.Ext(fp); len(v) > 0 {
- pkg.Format = PackageType(filepath.Ext(fp)[1:])
- }
-
- pkg.file, err = os.Open(fp)
- if err != nil {
- return nil, err
- }
- r, err := NewCompressedFileReader(
- pkg.file,
- pkg.Format,
- )
- if err != nil {
- return nil, err
- }
- pkg.tarR = tar.NewReader(r)
- if err != nil {
- return nil, err
- }
- pkg.r = pkg.tarR
-
- pkg.pkgName, err = PackageName(fp)
- if err != nil {
- return nil, err
- }
-
- pkg.pkgInfo.Name = PackageBase(fp)
- pkg.pkgInfo.PackageLocation = fp
-
- size, err := FileSize(fp)
- if err != nil {
- return nil, err
- }
- pkg.pkgInfo.CompressedPackageSize = HumanReadableSize(size)
-
- return &pkg, nil
-}
-
-func (s *SlackwarePkg) PkgInfo() *PackageInfo {
- ret := s.pkgInfo
- ret.UncompressedPackageSize = HumanReadableSize(s.uncompressedSize)
- return &ret
-}
-
-func (s *SlackwarePkg) Close() error {
- return s.file.Close()
-}
-
-func (s *SlackwarePkg) Next() (*tar.Header, error) {
- h, err := s.tarR.Next()
- if err != nil {
- return nil, err
- }
- s.r = s.tarR
-
- s.pkgInfo.FileList = append(s.pkgInfo.FileList, h.Name)
- if h.Name == PackageSlackDescFile {
- var buf bytes.Buffer
- _, err := io.Copy(&buf, s.r)
- if err != nil {
- return nil, err
- }
- s.pkgInfo.PackageDescription = parseSlackDesc(buf.String(), s.pkgName)
- s.r = bytes.NewReader(buf.Bytes())
- }
- return h, nil
-}
-
-func (s *SlackwarePkg) Read(b []byte) (int, error) {
- n, err := s.r.Read(b)
- s.uncompressedSize += int64(n)
- return n, err
-}
-
-// PackageBase is the package's filename without the (supported) extension.
-func PackageBase(fp string) string {
- filename := filepath.Base(fp)
- ext := filepath.Ext(filename)
- for _, v := range SupportedPackageTypes {
- if "."+v == ext {
- return filename[:(len(filename) - len(ext))]
- }
- }
- return filename
-}
-
-func PackageName(fp string) (string, error) {
- base := PackageBase(fp)
- strs := strings.Split(base, "-")
- if len(strs) < 4 {
- return "", errors.Errorf("badly formatted package name '%s'", fp)
- }
- name := strings.Join(strs[:(len(strs)-3)], "-")
- return name, nil
-}
-
-type PackageInfo struct {
- Name string
- // TODO: Should be size
- CompressedPackageSize string
- UncompressedPackageSize string
- PackageLocation string
- PackageDescription string
- MD5Sum string
- FileList []string
-}
-
-func changeExt(fp string, ext string) string {
- oldExt := filepath.Ext(fp)
- ret := fp[:(len(fp) - len(oldExt))]
- ret = ret + "." + ext
- return ret
-}
-
-func parseSlackDesc(str string, shortname string) string {
- // TODO: What does this do?
- //echo "PACKAGE DESCRIPTION:" >> $ADM_DIR/packages/$shortname
- //grep "^$packagebase:" $DESCRIPTION >> $ADM_DIR/packages/$shortname 2> /dev/null
- //if [ "$shortname" != "$packagebase" ]; then
- // grep "^$shortname:" $DESCRIPTION >> $ADM_DIR/packages/$shortname 2> /dev/null
- //fi
- lines := strings.Split(str, "\n")
- var kept []string
- for _, l := range lines {
- if strings.HasPrefix(l, shortname) {
- kept = append(kept, l)
- }
- }
- return strings.Join(kept, "\n")
-}
-
-func GetUncompressedSize(fp string) (int64, error) {
- f, err := os.Open(fp)
- if err != nil {
- return 0, err
- }
- defer f.Close()
-
- ext := filepath.Ext(fp)[1:]
- r, err := NewCompressedFileReader(f, PackageType(ext))
- if err != nil {
- return 0, err
- }
-
- var size int64
- var buf [1024]byte
- for {
- n, err := r.Read(buf[:])
- if err == io.EOF {
- break
- } else if err != nil {
- return 0, err
- }
- size += int64(n)
- }
- return size, nil
-}
-
-// Use package name or package base for name
-func GetPackageInfo(root string, pkgName string) (*PackageInfo, error) {
- infoPath := TargetPackageInfoPath(root, pkgName)
- info, err := ReadPackageInfo(infoPath)
- return info, errors.Wrap(err, "getting package information")
-}
-
-func ReadPackageInfo(fp string) (*PackageInfo, error) {
- f, err := os.Open(fp)
- if err != nil {
- return nil, err
- }
- defer f.Close()
-
- buf, err := io.ReadAll(f)
- if err != nil {
- return nil, err
- }
- info, err := ParsePackageInfo(string(buf))
- if err != nil {
- return nil, err
- }
-
- return info, nil
-}
-
-func ParsePackageInfo(text string) (*PackageInfo, error) {
- keys := map[string]struct{}{
- "COMPRESSED PACKAGE SIZE": {},
- "FILE LIST": {},
- "MD5SUM": {},
- "PACKAGE DESCRIPTION": {},
- "PACKAGE LOCATION": {},
- "PACKAGE NAME": {},
- "UNCOMPRESSED PACKAGE SIZE": {},
- }
-
- pkg := PackageInfo{}
- scanner := bufio.NewScanner(bytes.NewBufferString(text))
- for scanner.Scan() {
- var k string
-
- l := scanner.Text()
- strs := strings.Split(l, ":")
- if len(strs) != 2 {
- continue
- }
- k = strings.TrimSpace(strs[0])
- v := strings.TrimSpace(strs[1])
- _ = keys
-
- loop:
- for {
- switch k {
- case "PACKAGE NAME":
- pkg.Name = v
- case "COMPRESSED PACKAGE SIZE":
- pkg.CompressedPackageSize = v
- case "UNCOMPRESSED PACKAGE SIZE":
- pkg.UncompressedPackageSize = v
- case "MD5SUM":
- pkg.MD5Sum = v
- case "PACKAGE LOCATION":
- pkg.PackageLocation = v
- case "PACKAGE DESCRIPTION":
- for scanner.Scan() {
- l := scanner.Text()
- strs := strings.Split(l, ":")
- if len(strs) == 2 {
- k = strings.TrimSpace(strs[0])
- v = strings.TrimSpace(strs[1])
- if _, ok := keys[k]; ok {
- break
- }
- }
- if len(pkg.PackageDescription) > 0 {
- pkg.PackageDescription += "\n"
- }
- pkg.PackageDescription += scanner.Text()
- }
- continue loop
- case "FILE LIST":
- for scanner.Scan() {
- pkg.FileList = append(pkg.FileList, scanner.Text())
- }
- default:
- return nil, fmt.Errorf("unknown key '%s'", k)
- }
- break
- }
- }
- return &pkg, nil
-}
-
-type PackageFormatKey string
-
-type Encoder struct {
- w io.Writer
- MD5Sum bool
-}
-
-func NewEncoder(w io.Writer) *Encoder {
- return &Encoder{w: w}
-}
-
-func (s *Encoder) EnableMD5Sum(arg bool) {
- s.MD5Sum = arg
-}
-
-func (s *Encoder) Encode(pkg *PackageInfo) error {
- _, err := s.w.Write([]byte(fmt.Sprintf("PACKAGE NAME: %s\n", pkg.Name)))
- if err != nil {
- return err
- }
- _, err = s.w.Write([]byte(fmt.Sprintf("COMPRESSED PACKAGE SIZE: %s\n", pkg.CompressedPackageSize)))
- if err != nil {
- return err
- }
- _, err = s.w.Write([]byte(fmt.Sprintf("UNCOMPRESSED PACKAGE SIZE: %s\n", pkg.UncompressedPackageSize)))
- if err != nil {
- return err
- }
- _, err = s.w.Write([]byte(fmt.Sprintf("PACKAGE LOCATION: %s\n", pkg.PackageLocation)))
- if err != nil {
- return err
- }
- if s.MD5Sum {
- _, err = s.w.Write([]byte(fmt.Sprintf("PACKAGE MD5SUM: %s\n", pkg.MD5Sum)))
- if err != nil {
- return err
- }
- }
-
- _, err = s.w.Write([]byte(fmt.Sprintf("PACKAGE DESCRIPTION:\n%s\n", pkg.PackageDescription)))
- if err != nil {
- return err
- }
- _, err = s.w.Write([]byte("FILE LIST:\n"))
- if err != nil {
- return err
- }
- for _, f := range pkg.FileList {
- _, err = s.w.Write([]byte(f + "\n"))
- if err != nil {
- return err
- }
- }
- return nil
-}