package repokit import "crypto/md5" import "crypto/sha1" import "crypto/sha256" import "crypto/sha512" import "encoding/hex" import "fmt" import "hash" import "io" import "os" import "strings" // The code for rpm repo manipulation is based on // https://github.com/shanhai-repository/createrepo_go // RpmChecksumType is an enumeration of supported checksum types. // SHA is considered equivalent to SHA1 for compatibility with original createrepo. type RpmChecksumType int const ( RPM_CHECKSUM_UNKNOWN RpmChecksumType = iota RPM_CHECKSUM_MD5 RPM_CHECKSUM_SHA RPM_CHECKSUM_SHA1 RPM_CHECKSUM_SHA224 RPM_CHECKSUM_SHA256 RPM_CHECKSUM_SHA384 RPM_CHECKSUM_SHA512 RPM_CHECKSUM_SENTINEL ) // RpmCompressionType represents the type of compression. type RpmCompressionType int const ( RPM_COMPRESSION_AUTO_DETECT RpmCompressionType = iota RPM_COMPRESSION_UNKNOWN RPM_COMPRESSION_NONE RPM_COMPRESSION_GZ RPM_COMPRESSION_BZ2 RPM_COMPRESSION_XZ RPM_COMPRESSION_ZCK RPM_COMPRESSION_ZSTD RPM_COMPRESSION_SENTINEL ) type RpmDepType int const ( RPM_DEP_PROVIDES RpmDepType = iota RPM_DEP_CONFLICTS RPM_DEP_OBSOLETES RPM_DEP_REQUIRES RPM_DEP_SUGGESTS RPM_DEP_ENHANCES RPM_DEP_RECOMMENDS RPM_DEP_SUPPLEMENTS RPM_DEP_OLDSUGGESTS RPM_DEP_OLDENHANCES RPM_DEP_SENTINEL ) type RpmDepItem struct { Type RpmDepType NameTag int FlagsTag int VersionTag int } type RpmRepomdType string // --------------------------------------------------------- const RpmDefaultChecksum RpmChecksumType = RPM_CHECKSUM_SHA256 const RpmDefaultRepomdChecksum RpmChecksumType = RPM_CHECKSUM_SHA256 const RpmDefaultWorkers int = 5 const RpmDefaultChangelogLimit int = 10 const RpmDefaultCompressionType RpmCompressionType = RPM_COMPRESSION_ZSTD // extra RPMSENSE flags not defined in github.com/sassoftware/go-rpmutils const RPM_SENSE_STRONG uint64 = 1 << 27 const RPM_SENSE_MISSINGOK uint64 = 1 << 19 // some RPM tags const RPM_TAG_RECOMMENDNAME = 5046 const RPM_TAG_RECOMMENDVERSION = 5047 const RPM_TAG_RECOMMENDFLAGS = 5048 const RPM_TAG_SUGGESTNAME = 5049 const RPM_TAG_SUGGESTVERSION = 5050 const RPM_TAG_SUGGESTFLAGS = 5051 const RPM_TAG_SUPPLEMENTNAME = 5052 const RPM_TAG_SUPPLEMENTVERSION = 5053 const RPM_TAG_SUPPLEMENTFLAGS = 5054 const RPM_TAG_ENHANCENAME = 5055 const RPM_TAG_ENHANCEVERSION = 5056 const RPM_TAG_ENHANCEFLAGS = 5057 const RPM_XML_NS_COMMON string = "http://linux.duke.edu/metadata/common" const RPM_XML_NS_FILELISTS string = "http://linux.duke.edu/metadata/filelists" const RPM_XML_NS_FILELISTS_EXT string = "http://linux.duke.edu/metadata/filelists-ext" const RPM_XML_NS_OTHER string = "http://linux.duke.edu/metadata/other" const RPM_XML_NS_REPOMD string = "http://linux.duke.edu/metadata/repo" const RPM_XML_NS_RPM string = "http://linux.duke.edu/metadata/rpm" const RpmLocationHrefPrefix string = "repodata/" const RpmRepomdTypePrimary RpmRepomdType = "primary" const RpmRepomdTypeFilelists RpmRepomdType = "filelists" const RpmRepomdTypeOther RpmRepomdType = "other" const RpmRepomdTypeFilelistsExt RpmRepomdType = "filelists-ext" // --------------------------------------------------------- func RpmChecksumName(checksum_type RpmChecksumType) string { var name string switch checksum_type { case RPM_CHECKSUM_UNKNOWN: name = "Unknown checksum" case RPM_CHECKSUM_MD5: name = "md5" case RPM_CHECKSUM_SHA: name = "sha" case RPM_CHECKSUM_SHA1: name = "sha1" case RPM_CHECKSUM_SHA224: name = "sha224" case RPM_CHECKSUM_SHA256: name = "sha256" case RPM_CHECKSUM_SHA384: name = "sha384" case RPM_CHECKSUM_SHA512: name = "sha512" default: name = "" } return name } // --------------------------------------------------------- func CompressionSuffix(compression_type RpmCompressionType) string { var suffix string switch compression_type { case RPM_COMPRESSION_GZ: suffix = ".gz" case RPM_COMPRESSION_BZ2: suffix = ".bz2" case RPM_COMPRESSION_XZ: suffix = ".xz" case RPM_COMPRESSION_ZCK: suffix = ".zck" case RPM_COMPRESSION_ZSTD: suffix = ".zst" default: suffix = "" } return suffix } // --------------------------------------------------------- func rpm_repomd_record_type_value(record_type RpmRepomdType) int { var value int switch record_type { case "primary": value = 1 case "filelists": value = 2 case "other": value = 3 case "primary_db": value = 4 case "filelists_db": value = 5 case "other_db": value = 6 case "primary_zck": value = 7 case "filelists_zck": value = 8 case "other_zck": value = 9 default: value = 10 } return value } func rpm_repomd_record_cmp(a *RpmRepomdRecord, b *RpmRepomdRecord) int { var a_val int var b_val int var ret int a_val = rpm_repomd_record_type_value(RpmRepomdType(a.Type)) b_val = rpm_repomd_record_type_value(RpmRepomdType(b.Type)) if a_val < b_val { return -1 } if a_val > b_val { return 1 } ret = strings.Compare(a.Type, b.Type) if ret != 0 { return ret } ret = strings.Compare(a.Location.Href, b.Location.Href) if ret != 0 { return ret } return strings.Compare(a.Location.XMLBase, b.Location.XMLBase) } // --------------------------------------------------------- func rpm_checksum_bytes(content []byte, checksum_type RpmChecksumType) (string, error) { var hasher hash.Hash var sum []byte var checksum string switch checksum_type { case RPM_CHECKSUM_MD5: hasher = md5.New() case RPM_CHECKSUM_SHA: hasher = sha1.New() case RPM_CHECKSUM_SHA1: hasher = sha1.New() case RPM_CHECKSUM_SHA224: hasher = sha256.New224() case RPM_CHECKSUM_SHA256: hasher = sha256.New() case RPM_CHECKSUM_SHA384: hasher = sha512.New384() case RPM_CHECKSUM_SHA512: hasher = sha512.New() case RPM_CHECKSUM_UNKNOWN: fallthrough default: return "", fmt.Errorf("unknown checksum type") } hasher.Write(content) sum = hasher.Sum(nil) checksum = hex.EncodeToString(sum) return checksum, nil } func rpm_checksum_file(filename string, checksum_type RpmChecksumType) (string, error) { var f *os.File var err error var hasher hash.Hash var sum []byte var checksum string f, err = os.Open(filename) if err != nil { return "", err } defer f.Close() switch checksum_type { case RPM_CHECKSUM_MD5: hasher = md5.New() case RPM_CHECKSUM_SHA: hasher = sha1.New() case RPM_CHECKSUM_SHA1: hasher = sha1.New() case RPM_CHECKSUM_SHA224: hasher = sha256.New224() case RPM_CHECKSUM_SHA256: hasher = sha256.New() case RPM_CHECKSUM_SHA384: hasher = sha512.New384() case RPM_CHECKSUM_SHA512: hasher = sha512.New() case RPM_CHECKSUM_UNKNOWN: fallthrough default: return "", fmt.Errorf("unknown checksum type") } _, err = io.Copy(hasher, f) if err != nil { return "", err } sum = hasher.Sum(nil) checksum = hex.EncodeToString(sum) return checksum, nil } // --------------------------------------------------------- func rpm_init_xml_struct_all() *RpmXmlStructAll { var result *RpmXmlStructAll result = &RpmXmlStructAll{} result.RpmPrimaryXMLData = RpmPrimaryXMLData{Xmlns: RPM_XML_NS_COMMON, XmlnsRPM: RPM_XML_NS_RPM} result.RpmFilelistsXMLData = RpmFilelistsXMLData{Xmlns: RPM_XML_NS_FILELISTS} result.RpmOtherXMLData = RpmOtherXMLData{Xmlns: RPM_XML_NS_OTHER} result.RpmFilelistsExtXMLData = RpmFilelistsExtXMLData{Xmlns: RPM_XML_NS_FILELISTS_EXT} return result }