diff options
Diffstat (limited to 'pkgtools.go')
-rw-r--r-- | pkgtools.go | 534 |
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 -} |