diff --git a/pkg/entry.go b/pkg/entry.go index 2d5e153..1c2a264 100644 --- a/pkg/entry.go +++ b/pkg/entry.go @@ -3,7 +3,9 @@ package rpmdb import ( "bytes" "encoding/binary" + "fmt" "io" + "strings" "unsafe" "golang.org/x/xerrors" @@ -67,6 +69,24 @@ type entryInfo struct { Count uint32 /*!< Number of tag elements. */ } +func (ei entryInfo) TagName() string { + tagname, ok := tagNames[ei.Tag] + if !ok { + tagname = fmt.Sprintf("tag#%v", ei.Tag) + } + + return tagname +} + +func (ei entryInfo) TypeName() string { + typename, ok := typeNames[ei.Tag] + if !ok { + typename = fmt.Sprintf("type#%v", ei.Tag) + } + + return typename +} + // ref. https://github.com/rpm-software-management/rpm/blob/rpm-4.14.3-release/lib/header.c#L88-L94 type indexEntry struct { Info entryInfo @@ -75,6 +95,98 @@ type indexEntry struct { Data []byte } +const ( + sizeOfInt32 = 4 + sizeOfUInt16 = 2 +) + +func (ie indexEntry) ParseString() (string, error) { + if ie.Info.Type != RPM_STRING_TYPE { + return "", xerrors.Errorf("invalid tag type for string field: %v", ie.Info.TypeName()) + } + + result := string(bytes.TrimRight(ie.Data, "\x00")) + + switch (ie.Info.Tag) { + case RPMTAG_SOURCERPM, RPMTAG_LICENSE, RPMTAG_VENDOR: + if result == "(none)" { + result = "" + } + } + + return result, nil +} + +func (ie indexEntry) ParseI18nString() (string, error) { + // some libraries have a string value instead of international string, + // so accounting for both + if ie.Info.Type != RPM_I18NSTRING_TYPE && ie.Info.Type != RPM_STRING_TYPE { + return "", xerrors.Errorf("invalid tag type for international string field: %v", + ie.Info.TypeName()) + } + + // since this is an international string, getting the first null terminated string + return string(bytes.Split(ie.Data, []byte{0})[0]), nil +} + +func (ie indexEntry) ParseStringArray() ([]string, error) { + if ie.Info.Type != RPM_STRING_ARRAY_TYPE { + return nil, xerrors.Errorf("invalid tag type for string array field: %v", + ie.Info.TypeName()) + } + + return strings.Split(string(bytes.TrimRight(ie.Data, "\x00")), "\x00"), nil +} + +func (ie indexEntry) ParseUint16Array() ([]uint16, error) { + length := ie.Length / sizeOfUInt16 + values := make([]uint16, length) + reader := bytes.NewReader(ie.Data) + if err := binary.Read(reader, binary.BigEndian, &values); err != nil { + return nil, xerrors.Errorf("failed to read binary: %w", err) + } + return values, nil +} + +func (ie indexEntry) ParseInt32() (int, error) { + if ie.Info.Type != RPM_INT32_TYPE { + return 0, xerrors.Errorf("invalid tag type for int32 field: %v", + ie.Info.TypeName()) + } + + var value int32 + reader := bytes.NewReader(ie.Data) + if err := binary.Read(reader, binary.BigEndian, &value); err != nil { + return 0, xerrors.Errorf("failed to read binary: %w", err) + } + return int(value), nil +} + +func (ie indexEntry) ParseInt32Array() ([]int32, error) { + if ie.Info.Type != RPM_INT32_TYPE { + return nil, xerrors.Errorf("invalid tag type for int32 array field: %v", + ie.Info.TypeName()) + } + + length := ie.Length / sizeOfInt32 + values := make([]int32, length) + reader := bytes.NewReader(ie.Data) + if err := binary.Read(reader, binary.BigEndian, &values); err != nil { + return nil, xerrors.Errorf("failed to read binary: %w", err) + } + return values, nil +} + +func (ie indexEntry) ParseInt64() (int, error) { + var value int64 + + reader := bytes.NewReader(ie.Data) + if err := binary.Read(reader, binary.BigEndian, &value); err != nil { + return 0, xerrors.Errorf("failed to read binary: %w", err) + } + return int(value), nil +} + // ref. https://github.com/rpm-software-management/rpm/blob/rpm-4.14.3-release/lib/header_internal.h#L23 type hdrblob struct { peList []entryInfo diff --git a/pkg/package.go b/pkg/package.go index c73baf5..78cd50b 100644 --- a/pkg/package.go +++ b/pkg/package.go @@ -5,7 +5,6 @@ import ( "encoding/binary" "fmt" "path/filepath" - "strings" "time" "golang.org/x/xerrors" @@ -50,313 +49,205 @@ type FileInfo struct { func getNEVRA(indexEntries []indexEntry) (*PackageInfo, error) { pkgInfo := &PackageInfo{} for _, ie := range indexEntries { + var err error switch ie.Info.Tag { - case RPMTAG_DIRINDEXES: - if ie.Info.Type != RPM_INT32_TYPE { - return nil, xerrors.New("invalid tag dir indexes") - } - - dirIndexes, err := parseInt32Array(ie.Data, ie.Length) - if err != nil { - return nil, xerrors.Errorf("unable to read dir indexes: %w", err) - } - pkgInfo.DirIndexes = dirIndexes - case RPMTAG_DIRNAMES: - if ie.Info.Type != RPM_STRING_ARRAY_TYPE { - return nil, xerrors.New("invalid tag dir names") - } - pkgInfo.DirNames = parseStringArray(ie.Data) - case RPMTAG_BASENAMES: - if ie.Info.Type != RPM_STRING_ARRAY_TYPE { - return nil, xerrors.New("invalid tag base names") - } - pkgInfo.BaseNames = parseStringArray(ie.Data) + // RPM_STRING_TYPE case RPMTAG_MODULARITYLABEL: - if ie.Info.Type != RPM_STRING_TYPE { - return nil, xerrors.New("invalid tag modularitylabel") - } - pkgInfo.Modularitylabel = string(bytes.TrimRight(ie.Data, "\x00")) + pkgInfo.Modularitylabel, err = ie.ParseString() case RPMTAG_NAME: - if ie.Info.Type != RPM_STRING_TYPE { - return nil, xerrors.New("invalid tag name") - } - pkgInfo.Name = string(bytes.TrimRight(ie.Data, "\x00")) - case RPMTAG_EPOCH: - if ie.Info.Type != RPM_INT32_TYPE { - return nil, xerrors.New("invalid tag epoch") - } - - if ie.Data != nil { - value, err := parseInt32(ie.Data) - if err != nil { - return nil, xerrors.Errorf("failed to parse epoch: %w", err) - } - pkgInfo.Epoch = &value - } + pkgInfo.Name, err = ie.ParseString() case RPMTAG_VERSION: - if ie.Info.Type != RPM_STRING_TYPE { - return nil, xerrors.New("invalid tag version") - } - pkgInfo.Version = string(bytes.TrimRight(ie.Data, "\x00")) + pkgInfo.Version, err = ie.ParseString() case RPMTAG_RELEASE: - if ie.Info.Type != RPM_STRING_TYPE { - return nil, xerrors.New("invalid tag release") - } - pkgInfo.Release = string(bytes.TrimRight(ie.Data, "\x00")) + pkgInfo.Release, err = ie.ParseString() case RPMTAG_ARCH: - if ie.Info.Type != RPM_STRING_TYPE { - return nil, xerrors.New("invalid tag arch") - } - pkgInfo.Arch = string(bytes.TrimRight(ie.Data, "\x00")) + pkgInfo.Arch, err = ie.ParseString() case RPMTAG_SOURCERPM: - if ie.Info.Type != RPM_STRING_TYPE { - return nil, xerrors.New("invalid tag sourcerpm") - } - pkgInfo.SourceRpm = string(bytes.TrimRight(ie.Data, "\x00")) - if pkgInfo.SourceRpm == "(none)" { - pkgInfo.SourceRpm = "" - } + pkgInfo.SourceRpm, err = ie.ParseString() case RPMTAG_LICENSE: - if ie.Info.Type != RPM_STRING_TYPE { - return nil, xerrors.New("invalid tag license") - } - pkgInfo.License = string(bytes.TrimRight(ie.Data, "\x00")) - if pkgInfo.License == "(none)" { - pkgInfo.License = "" - } + pkgInfo.License, err = ie.ParseString() case RPMTAG_VENDOR: - if ie.Info.Type != RPM_STRING_TYPE { - return nil, xerrors.New("invalid tag vendor") - } - pkgInfo.Vendor = string(bytes.TrimRight(ie.Data, "\x00")) - if pkgInfo.Vendor == "(none)" { - pkgInfo.Vendor = "" - } - case RPMTAG_SIZE: - if ie.Info.Type != RPM_INT32_TYPE { - return nil, xerrors.New("invalid tag size") - } + pkgInfo.Vendor, err = ie.ParseString() - size, err := parseInt32(ie.Data) - if err != nil { - return nil, xerrors.Errorf("failed to parse size: %w", err) - } - pkgInfo.Size = size - case RPMTAG_FILEDIGESTALGO: - // note: all digests within a package entry only supports a single digest algorithm (there may be future support for - // algorithm noted for each file entry, but currently unimplemented: https://github.com/rpm-software-management/rpm/blob/0b75075a8d006c8f792d33a57eae7da6b66a4591/lib/rpmtag.h#L256) - if ie.Info.Type != RPM_INT32_TYPE { - return nil, xerrors.New("invalid tag digest algo") - } - - digestAlgorithm, err := parseInt32(ie.Data) - if err != nil { - return nil, xerrors.Errorf("failed to parse digest algo: %w", err) - } + // RPM_I18NSTRING_TYPE + case RPMTAG_SUMMARY: + pkgInfo.Summary, err = ie.ParseI18nString() - pkgInfo.DigestAlgorithm = DigestAlgorithm(digestAlgorithm) - case RPMTAG_FILESIZES: - // note: there is no distinction between int32, uint32, and []uint32 - if ie.Info.Type != RPM_INT32_TYPE { - return nil, xerrors.New("invalid tag file-sizes") - } - fileSizes, err := parseInt32Array(ie.Data, ie.Length) - if err != nil { - return nil, xerrors.Errorf("failed to parse file-sizes: %w", err) - } - pkgInfo.FileSizes = fileSizes + // RPM_STRING_ARRAY_TYPE + case RPMTAG_DIRNAMES: + pkgInfo.DirNames, err = ie.ParseStringArray() + case RPMTAG_BASENAMES: + pkgInfo.BaseNames, err = ie.ParseStringArray() case RPMTAG_FILEDIGESTS: - if ie.Info.Type != RPM_STRING_ARRAY_TYPE { - return nil, xerrors.New("invalid tag file-digests") - } - pkgInfo.FileDigests = parseStringArray(ie.Data) - case RPMTAG_FILEMODES: - // note: there is no distinction between int16, uint16, and []uint16 - if ie.Info.Type != RPM_INT16_TYPE { - return nil, xerrors.New("invalid tag file-modes") - } - fileModes, err := uint16Array(ie.Data, ie.Length) - if err != nil { - return nil, xerrors.Errorf("failed to parse file-modes: %w", err) - } - pkgInfo.FileModes = fileModes - case RPMTAG_FILEFLAGS: - // note: there is no distinction between int32, uint32, and []uint32 - if ie.Info.Type != RPM_INT32_TYPE { - return nil, xerrors.New("invalid tag file-flags") - } - fileFlags, err := parseInt32Array(ie.Data, ie.Length) - if err != nil { - return nil, xerrors.Errorf("failed to parse file-flags: %w", err) - } - pkgInfo.FileFlags = fileFlags + pkgInfo.FileDigests, err = ie.ParseStringArray() case RPMTAG_FILEUSERNAME: - if ie.Info.Type != RPM_STRING_ARRAY_TYPE { - return nil, xerrors.New("invalid tag usernames") - } - pkgInfo.UserNames = parseStringArray(ie.Data) + pkgInfo.UserNames, err = ie.ParseStringArray() case RPMTAG_FILEGROUPNAME: - if ie.Info.Type != RPM_STRING_ARRAY_TYPE { - return nil, xerrors.New("invalid tag groupnames") - } - pkgInfo.GroupNames = parseStringArray(ie.Data) - case RPMTAG_SUMMARY: - // some libraries have a string value instead of international string, so accounting for both - if ie.Info.Type != RPM_I18NSTRING_TYPE && ie.Info.Type != RPM_STRING_TYPE { - return nil, xerrors.New("invalid tag summary") - } - // since this is an international string, getting the first null terminated string - pkgInfo.Summary = string(bytes.Split(ie.Data, []byte{0})[0]) - case RPMTAG_PGP: - type pgpSig struct { - _ [3]byte - Date int32 - KeyID [8]byte - PubKeyAlgo uint8 - HashAlgo uint8 - } - - type textSig struct { - _ [2]byte - PubKeyAlgo uint8 - HashAlgo uint8 - _ [4]byte - Date int32 - _ [4]byte - KeyID [8]byte - } + pkgInfo.GroupNames, err = ie.ParseStringArray() - type pgp4Sig struct { - _ [2]byte - PubKeyAlgo uint8 - HashAlgo uint8 - _ [17]byte - KeyID [8]byte - _ [2]byte - Date int32 - } + // note: there is no distinction between int16, uint16, and []uint16 + // RPM_INT16_TYPE (array variant) + case RPMTAG_FILEMODES: + pkgInfo.FileModes, err = ie.ParseUint16Array() - pubKeyLookup := map[uint8]string{ - 0x01: "RSA", - } - hashLookup := map[uint8]string{ - 0x02: "SHA1", - 0x08: "SHA256", - } + // note: there is no distinction between int32, uint32, and []uint32 + // RPM_INT32_TYPE (scalar variant) + case RPMTAG_SIZE: + pkgInfo.Size, err = ie.ParseInt32() - if ie.Info.Type != RPM_BIN_TYPE { - return nil, xerrors.New("invalid PGP signature") - } + // RPM_INT32_TYPE (array variant) + case RPMTAG_DIRINDEXES: + pkgInfo.DirIndexes, err = ie.ParseInt32Array() + case RPMTAG_FILESIZES: + pkgInfo.FileSizes, err = ie.ParseInt32Array() + case RPMTAG_FILEFLAGS: + pkgInfo.FileFlags, err = ie.ParseInt32Array() - var tag, signatureType, version uint8 - r := bytes.NewReader(ie.Data) - err := binary.Read(r, binary.BigEndian, &tag) - if err != nil { - return nil, err - } - err = binary.Read(r, binary.BigEndian, &signatureType) - if err != nil { - return nil, err + // Special handling + case RPMTAG_EPOCH: + if ie.Data != nil { + value, err := ie.ParseInt32() + if err != nil { + break + } + pkgInfo.Epoch = &value } - err = binary.Read(r, binary.BigEndian, &version) + case RPMTAG_FILEDIGESTALGO: + // note: all digests within a package entry only supports a single + // digest algorithm (there may be future support for algorithm noted for + // each file entry, but currently unimplemented: + // https://github.com/rpm-software-management/rpm/blob/0b75075a8d006c8f792d33a57eae7da6b66a4591/lib/rpmtag.h#L256) + digestAlgorithm, err := ie.ParseInt32() if err != nil { - return nil, err + break } - var pubKeyAlgo, hashAlgo, pkgDate string - var keyId [8]byte - - switch signatureType { - case 0x01: - switch version { - case 0x1c: - sig := textSig{} - err = binary.Read(r, binary.BigEndian, &sig) - if err != nil { - return nil, xerrors.Errorf("invalid PGP signature on decode: %w", err) - } - pubKeyAlgo = pubKeyLookup[sig.PubKeyAlgo] - hashAlgo = hashLookup[sig.HashAlgo] - pkgDate = time.Unix(int64(sig.Date), 0).UTC().Format("Mon Jan _2 15:04:05 2006") - keyId = sig.KeyID - default: - sig := pgpSig{} - err = binary.Read(r, binary.BigEndian, &sig) - if err != nil { - return nil, xerrors.Errorf("invalid PGP signature on decode: %w", err) - } - pubKeyAlgo = pubKeyLookup[sig.PubKeyAlgo] - hashAlgo = hashLookup[sig.HashAlgo] - pkgDate = time.Unix(int64(sig.Date), 0).UTC().Format("Mon Jan _2 15:04:05 2006") - keyId = sig.KeyID - } - case 0x02: - switch version { - case 0x33: - sig := pgp4Sig{} - err = binary.Read(r, binary.BigEndian, &sig) - if err != nil { - return nil, xerrors.Errorf("invalid PGP signature on decode: %w", err) - } - pubKeyAlgo = pubKeyLookup[sig.PubKeyAlgo] - hashAlgo = hashLookup[sig.HashAlgo] - pkgDate = time.Unix(int64(sig.Date), 0).UTC().Format("Mon Jan _2 15:04:05 2006") - keyId = sig.KeyID - default: - sig := pgpSig{} - err = binary.Read(r, binary.BigEndian, &sig) - if err != nil { - return nil, xerrors.Errorf("invalid PGP signature on decode: %w", err) - } - pubKeyAlgo = pubKeyLookup[sig.PubKeyAlgo] - hashAlgo = hashLookup[sig.HashAlgo] - pkgDate = time.Unix(int64(sig.Date), 0).UTC().Format("Mon Jan _2 15:04:05 2006") - keyId = sig.KeyID - } - } - pkgInfo.PGP = fmt.Sprintf("%s/%s, %s, Key ID %x", pubKeyAlgo, hashAlgo, pkgDate, keyId) + pkgInfo.DigestAlgorithm = DigestAlgorithm(digestAlgorithm) + case RPMTAG_PGP: + pkgInfo.PGP, err = parsePGPSignature(ie) + } + + if err != nil { + return nil, xerrors.Errorf("error while parsing %v: %w", + ie.Info.TagName(), err) } } return pkgInfo, nil } -const ( - sizeOfInt32 = 4 - sizeOfUInt16 = 2 -) +func parsePGPSignature(ie indexEntry) (string, error) { + type pgpSig struct { + _ [3]byte + Date int32 + KeyID [8]byte + PubKeyAlgo uint8 + HashAlgo uint8 + } -func parseInt32Array(data []byte, arraySize int) ([]int32, error) { - length := arraySize / sizeOfInt32 - values := make([]int32, length) - reader := bytes.NewReader(data) - if err := binary.Read(reader, binary.BigEndian, &values); err != nil { - return nil, xerrors.Errorf("failed to read binary: %w", err) + type textSig struct { + _ [2]byte + PubKeyAlgo uint8 + HashAlgo uint8 + _ [4]byte + Date int32 + _ [4]byte + KeyID [8]byte } - return values, nil -} -func parseInt32(data []byte) (int, error) { - var value int32 - reader := bytes.NewReader(data) - if err := binary.Read(reader, binary.BigEndian, &value); err != nil { - return 0, xerrors.Errorf("failed to read binary: %w", err) + type pgp4Sig struct { + _ [2]byte + PubKeyAlgo uint8 + HashAlgo uint8 + _ [17]byte + KeyID [8]byte + _ [2]byte + Date int32 } - return int(value), nil -} -func uint16Array(data []byte, arraySize int) ([]uint16, error) { - length := arraySize / sizeOfUInt16 - values := make([]uint16, length) - reader := bytes.NewReader(data) - if err := binary.Read(reader, binary.BigEndian, &values); err != nil { - return nil, xerrors.Errorf("failed to read binary: %w", err) + pubKeyLookup := map[uint8]string{ + 0x01: "RSA", } - return values, nil -} + hashLookup := map[uint8]string{ + 0x02: "SHA1", + 0x08: "SHA256", + } + + if ie.Info.Type != RPM_BIN_TYPE { + return "", xerrors.New("invalid PGP signature") + } + + var tag, signatureType, version uint8 + r := bytes.NewReader(ie.Data) + err := binary.Read(r, binary.BigEndian, &tag) + if err != nil { + return "", err + } + err = binary.Read(r, binary.BigEndian, &signatureType) + if err != nil { + return "", err + } + err = binary.Read(r, binary.BigEndian, &version) + if err != nil { + return "", err + } + + var pubKeyAlgo, hashAlgo, pkgDate string + var keyId [8]byte + + switch signatureType { + case 0x01: + switch version { + case 0x1c: + sig := textSig{} + err = binary.Read(r, binary.BigEndian, &sig) + if err != nil { + return "", xerrors.Errorf("invalid PGP signature on decode: %w", err) + } + pubKeyAlgo = pubKeyLookup[sig.PubKeyAlgo] + hashAlgo = hashLookup[sig.HashAlgo] + pkgDate = time.Unix(int64(sig.Date), 0).UTC().Format("Mon Jan _2 15:04:05 2006") + keyId = sig.KeyID + default: + sig := pgpSig{} + err = binary.Read(r, binary.BigEndian, &sig) + if err != nil { + return "", xerrors.Errorf("invalid PGP signature on decode: %w", err) + } + pubKeyAlgo = pubKeyLookup[sig.PubKeyAlgo] + hashAlgo = hashLookup[sig.HashAlgo] + pkgDate = time.Unix(int64(sig.Date), 0).UTC().Format("Mon Jan _2 15:04:05 2006") + keyId = sig.KeyID + } + case 0x02: + switch version { + case 0x33: + sig := pgp4Sig{} + err = binary.Read(r, binary.BigEndian, &sig) + if err != nil { + return "", xerrors.Errorf("invalid PGP signature on decode: %w", err) + } + pubKeyAlgo = pubKeyLookup[sig.PubKeyAlgo] + hashAlgo = hashLookup[sig.HashAlgo] + pkgDate = time.Unix(int64(sig.Date), 0).UTC().Format("Mon Jan _2 15:04:05 2006") + keyId = sig.KeyID + default: + sig := pgpSig{} + err = binary.Read(r, binary.BigEndian, &sig) + if err != nil { + return "", xerrors.Errorf("invalid PGP signature on decode: %w", err) + } + pubKeyAlgo = pubKeyLookup[sig.PubKeyAlgo] + hashAlgo = hashLookup[sig.HashAlgo] + pkgDate = time.Unix(int64(sig.Date), 0).UTC().Format("Mon Jan _2 15:04:05 2006") + keyId = sig.KeyID + } + } + + result := fmt.Sprintf("%s/%s, %s, Key ID %x", + pubKeyAlgo, hashAlgo, pkgDate, keyId) -func parseStringArray(data []byte) []string { - return strings.Split(string(bytes.TrimRight(data, "\x00")), "\x00") + return result, nil } func (p *PackageInfo) InstalledFileNames() ([]string, error) { diff --git a/pkg/rpmtagnames.go b/pkg/rpmtagnames.go new file mode 100644 index 0000000..8e0c3f4 --- /dev/null +++ b/pkg/rpmtagnames.go @@ -0,0 +1,43 @@ +package rpmdb +// generated by tagnames.sh; DO NOT EDIT + +var tagNames = map[int32]string { + RPMTAG_HEADERIMAGE : "RPMTAG_HEADERIMAGE", + RPMTAG_HEADERSIGNATURES : "RPMTAG_HEADERSIGNATURES", + RPMTAG_HEADERIMMUTABLE : "RPMTAG_HEADERIMMUTABLE", + RPMTAG_HEADERI18NTABLE : "RPMTAG_HEADERI18NTABLE", + RPMTAG_PGP : "RPMTAG_PGP", + RPMTAG_NAME : "RPMTAG_NAME", + RPMTAG_VERSION : "RPMTAG_VERSION", + RPMTAG_RELEASE : "RPMTAG_RELEASE", + RPMTAG_EPOCH : "RPMTAG_EPOCH", + RPMTAG_SUMMARY : "RPMTAG_SUMMARY", + RPMTAG_SIZE : "RPMTAG_SIZE", + RPMTAG_VENDOR : "RPMTAG_VENDOR", + RPMTAG_LICENSE : "RPMTAG_LICENSE", + RPMTAG_ARCH : "RPMTAG_ARCH", + RPMTAG_FILESIZES : "RPMTAG_FILESIZES", + RPMTAG_FILEMODES : "RPMTAG_FILEMODES", + RPMTAG_FILEDIGESTS : "RPMTAG_FILEDIGESTS", + RPMTAG_FILEFLAGS : "RPMTAG_FILEFLAGS", + RPMTAG_FILEUSERNAME : "RPMTAG_FILEUSERNAME", + RPMTAG_FILEGROUPNAME : "RPMTAG_FILEGROUPNAME", + RPMTAG_SOURCERPM : "RPMTAG_SOURCERPM", + RPMTAG_DIRINDEXES : "RPMTAG_DIRINDEXES", + RPMTAG_BASENAMES : "RPMTAG_BASENAMES", + RPMTAG_DIRNAMES : "RPMTAG_DIRNAMES", + RPMTAG_FILEDIGESTALGO : "RPMTAG_FILEDIGESTALGO", + RPMTAG_MODULARITYLABEL : "RPMTAG_MODULARITYLABEL", +} + +var typeNames = map[int32]string { + RPM_NULL_TYPE : "RPM_NULL_TYPE", + RPM_CHAR_TYPE : "RPM_CHAR_TYPE", + RPM_INT8_TYPE : "RPM_INT8_TYPE", + RPM_INT16_TYPE : "RPM_INT16_TYPE", + RPM_INT32_TYPE : "RPM_INT32_TYPE", + RPM_INT64_TYPE : "RPM_INT64_TYPE", + RPM_STRING_TYPE : "RPM_STRING_TYPE", + RPM_BIN_TYPE : "RPM_BIN_TYPE", + RPM_I18NSTRING_TYPE : "RPM_I18NSTRING_TYPE", +} diff --git a/pkg/rpmtags.go b/pkg/rpmtags.go index 2322c26..7fca0e1 100644 --- a/pkg/rpmtags.go +++ b/pkg/rpmtags.go @@ -1,4 +1,5 @@ package rpmdb +//go:generate bash tagnames.sh rpmtagnames.go const ( // ref. https://github.com/rpm-software-management/rpm/blob/rpm-4.14.3-release/lib/rpmtag.h#L34 @@ -10,10 +11,13 @@ const ( // rpmTag_e // ref. https://github.com/rpm-software-management/rpm/blob/rpm-4.14.3-release/lib/rpmtag.h#L34 + RPMTAG_PGP = 259 /* b */ + RPMTAG_NAME = 1000 /* s */ RPMTAG_VERSION = 1001 /* s */ RPMTAG_RELEASE = 1002 /* s */ RPMTAG_EPOCH = 1003 /* i */ + RPMTAG_SUMMARY = 1004 /* s */ RPMTAG_SIZE = 1009 /* i */ RPMTAG_VENDOR = 1011 /* s */ RPMTAG_LICENSE = 1014 /* s */ @@ -29,8 +33,6 @@ const ( RPMTAG_BASENAMES = 1117 /* s[] */ RPMTAG_DIRNAMES = 1118 /* s[] */ RPMTAG_FILEDIGESTALGO = 5011 /* i */ - RPMTAG_SUMMARY = 1004 /* s */ - RPMTAG_PGP = 259 /* b */ // rpmTag_enhances // https://github.com/rpm-software-management/rpm/blob/rpm-4.16.0-release/lib/rpmtag.h#L375 diff --git a/pkg/tagnames.sh b/pkg/tagnames.sh new file mode 100644 index 0000000..5aabbaf --- /dev/null +++ b/pkg/tagnames.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# +name="$(basename "$0")" +out="$1" + +if test -z "$out"; then + echo "usage: $name " >&2 + exit 1 +fi + +cat < $out +package rpmdb +// generated by $name; DO NOT EDIT + +var tagNames = map[int32]string { +END + +sed -ne '/RPMTAG_/s/.*\(RPMTAG_[A-Z0-9_]*\).*/ \1 : "\1",/p' rpmtags.go >> $out + +cat <> $out +} + +var typeNames = map[int32]string { +END + +grep -Ev '_(MIN|MAX)_' rpmtags.go | sed -ne '/RPM_[A-Z0-9]*_TYPE/s/.*\(RPM_[A-Z0-9]*_TYPE\).*/ \1 : "\1",/p' >> $out + +echo "}" >> $out