Documentation ¶
Overview ¶
Package rpm implements the rpm package file format.
package main import ( "fmt" "log" "github.com/cavaliergopher/rpm" ) func main() { pkg, err := rpm.Open("golang-1.17.2-1.el7.x86_64.rpm") if err != nil { log.Fatal(err) } fmt.Println("Package:", pkg) fmt.Println("Summary:", pkg.Summary()) // Output: // Package: golang-1.17.2-1.el7.x86_64 // Summary: The Go Programming Language }
For more information about the rpm file format, see:
http://ftp.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html
Packages are composed of two headers: the Signature header and the "Header" header. Each contains key-value pairs called tags. Tags map an integer key to a value whose data type will be one of the TagType types. Tag values can be decoded with the appropriate Tag method for the data type.
Many known tags are available as Package methods. For example, RPMTAG_NAME and RPMTAG_BUILDTIME are available as Package.Name and Package.BuildTime respectively.
fmt.Println(pkg.Name(), pkg.BuildTime())
Tags can be retrieved and decoded from the Signature or Header headers directly using Header.GetTag and their tag identifier.
const ( RPMTagName = 1000 RPMTagBuidlTime = 1006 ) fmt.Println( pkg.Header.GetTag(RPMTagName).String()), time.Unix(pkg.Header.GetTag(RPMTagBuildTime).Int64(), 0), )
Header.GetTag and all Tag methods will return a zero value if the header or the tag do not exist, or if the tag has a different data type.
You may enumerate all tags in a header with Header.Tags:
for id, tag := range pkg.Header.Tags { fmt.Println(id, tag.Type, tag.Value) }
Comparing versions ¶
In the rpm ecosystem, package versions are compared using EVR; epoch, version, release. Versions may be compared using the Compare function.
if rpm.Compare(pkgA, pkgB) == 1 { fmt.Println("A is more recent than B") }
Packages may be be sorted using the PackageSlice type which implements sort.Interface. Packages are sorted lexically by name ascending and then by version descending. Version is evaluated first by epoch, then by version string, then by release.
sort.Sort(PackageSlice(pkgs))
The Sort function is provided for your convenience.
rpm.Sort(pkgs)
Checksum validation ¶
Packages may be validated using MD5Check or GPGCheck. See the example for each function.
Extracting files ¶
The payload of an rpm package is typically archived in cpio format and compressed with xz. To decompress and unarchive an rpm payload, the reader that read the rpm package headers will be positioned at the beginning of the payload and can be reused with the appropriate Go packages for the rpm payload format.
You can check the archive format with Package.PayloadFormat and the compression algorithm with Package.PayloadCompression.
For the cpio archive format, the following package is recommended:
https://github.com/cavaliergopher/cpio
For xz compression, the following package is recommended:
https://github.com/ulikunitz/xz
See README.md for a working example of extracting files from a cpio/xz rpm package using these packages.
Example programs ¶
See cmd/rpmdump and cmd/rpminfo for example programs that emulate tools from the rpm ecosystem.
Index ¶
- Constants
- Variables
- func Compare(a, b Version) int
- func CompareVersions(a, b string) int
- func GPGCheck(r io.Reader, keyring openpgp.KeyRing) (string, error)
- func MD5Check(r io.Reader) error
- func OpenKeyRing(name ...string) (openpgp.KeyRing, error)
- func ReadKeyRing(r io.Reader) (openpgp.KeyRing, error)
- func Sort(x []*Package)
- type Dependency
- type FileInfo
- func (f *FileInfo) Digest() string
- func (f *FileInfo) Flags() int64
- func (f *FileInfo) Group() string
- func (f *FileInfo) IsDir() bool
- func (f *FileInfo) Linkname() string
- func (f *FileInfo) ModTime() time.Time
- func (f *FileInfo) Mode() os.FileMode
- func (f *FileInfo) Name() string
- func (f *FileInfo) Owner() string
- func (f *FileInfo) Size() int64
- func (f *FileInfo) String() string
- func (f *FileInfo) Sys() interface{}
- type GPGSignature
- type Header
- type Lead
- type Package
- func (c *Package) Architecture() string
- func (c *Package) ArchiveSize() uint64
- func (c *Package) BuildHost() string
- func (c *Package) BuildTime() time.Time
- func (c *Package) ChangeLog() []string
- func (c *Package) Conflicts() []Dependency
- func (c *Package) Description() string
- func (c *Package) Distribution() string
- func (c *Package) Enhances() []Dependency
- func (c *Package) Epoch() int
- func (c *Package) Files() []FileInfo
- func (c *Package) GIFImage() []byte
- func (c *Package) GPGSignature() GPGSignature
- func (c *Package) Groups() []string
- func (c *Package) Icon() []byte
- func (c *Package) InstallTime() time.Time
- func (c *Package) License() string
- func (c *Package) Name() string
- func (c *Package) Obsoletes() []Dependency
- func (c *Package) OldFilenames() []string
- func (c *Package) OperatingSystem() string
- func (c *Package) Packager() string
- func (c *Package) Patch() []string
- func (c *Package) PayloadCompression() string
- func (c *Package) PayloadFormat() string
- func (c *Package) Platform() string
- func (c *Package) PostInstallScript() string
- func (c *Package) PostUninstallScript() string
- func (c *Package) PreInstallScript() string
- func (c *Package) PreUninstallScript() string
- func (c *Package) Provides() []Dependency
- func (c *Package) RPMVersion() string
- func (c *Package) Recommends() []Dependency
- func (c *Package) Release() string
- func (c *Package) Requires() []Dependency
- func (c *Package) Size() uint64
- func (c *Package) Source() []string
- func (c *Package) SourceRPM() string
- func (c *Package) String() string
- func (c *Package) Suggests() []Dependency
- func (c *Package) Summary() string
- func (c *Package) Supplements() []Dependency
- func (c *Package) URL() string
- func (c *Package) Vendor() string
- func (c *Package) Version() string
- func (c *Package) XPMImage() []byte
- type PackageSlice
- type Tag
- type TagType
- type Version
Examples ¶
Constants ¶
const ( DepFlagAny = 0 DepFlagLesser = (1 << 1) DepFlagGreater = (1 << 2) DepFlagEqual = (1 << 3) DepFlagLesserOrEqual = (DepFlagEqual | DepFlagLesser) DepFlagGreaterOrEqual = (DepFlagEqual | DepFlagGreater) DepFlagPrereq = (1 << 6) DepFlagScriptPre = (1 << 9) DepFlagScriptPost = (1 << 10) DepFlagScriptPreUn = (1 << 11) DepFlagScriptPostUn = (1 << 12) DepFlagRpmlib = (1 << 24) )
Dependency flags indicate how versions comparisons should be computed when comparing versions of dependent packages.
const ( FileFlagNone = 0 FileFlagConfig = (1 << 0) // %%config FileFlagDoc = (1 << 1) // %%doc FileFlagIcon = (1 << 2) // %%donotuse FileFlagMissingOk = (1 << 3) // %%config(missingok) FileFlagNoReplace = (1 << 4) // %%config(noreplace) FileFlagGhost = (1 << 6) // %%ghost FileFlagLicense = (1 << 7) // %%license FileFlagReadme = (1 << 8) // %%readme FileFlagPubkey = (1 << 11) // %%pubkey FileFlagArtifact = (1 << 12) // %%artifact )
File flags make up some attributes of files depending on how they were specified in the rpmspec
const TimeFormat = "Mon Jan _2 15:04:05 2006"
TimeFormat is the time format used by the rpm ecosystem. The time being formatted must be in UTC for Format to generate the correct format.
Variables ¶
var ( // ErrMD5CheckFailed indicates that an rpm package failed MD5 checksum // validation. ErrMD5CheckFailed = fmt.Errorf("MD5 checksum validation failed") // ErrGPGCheckFailed indicates that an rpm package failed GPG signature // validation. ErrGPGCheckFailed = fmt.Errorf("GPG signature validation failed") )
var ErrNotRPMFile = errorf("invalid file descriptor")
ErrNotRPMFile indicates that the file is not an rpm package.
Functions ¶
func Compare ¶ added in v1.1.0
Compare compares the version details of two packages. Versions are compared by Epoch, Version and Release (EVR) in descending order of precedence.
If a is more recent than b, 1 is returned. If a is less recent than b, -1 is returned. If a and b are equal, 0 is returned.
This function does not consider if the two packages have the same name or if either package has been made obsolete by the other.
func CompareVersions ¶ added in v1.2.0
CompareVersion compares version strings. It does not consider package epochs or release numbers like Compare.
If a is more recent than b, 1 is returned. If a is less recent than b, -1 is returned. If a and b are equal, 0 is returned.
func GPGCheck ¶
GPGCheck validates the integrity of an rpm package file. Public keys in the given keyring are used to validate the package signature.
If validation fails, ErrGPGCheckFailed is returned.
Example ¶
ExampleGPGCheck reads a public GPG key and uses it to validate the signature of a local rpm package.
// read public key from gpgkey file keyring, err := OpenKeyRing("testdata/RPM-GPG-KEY-CentOS-7") if err != nil { log.Fatal(err) } // open a rpm package for reading f, err := os.Open("testdata/centos-release-7-2.1511.el7.centos.2.10.x86_64.rpm") if err != nil { log.Fatal(err) } defer f.Close() // validate gpg signature if signer, err := GPGCheck(f, keyring); err == nil { fmt.Printf("Package signed by '%s'\n", signer) } else if err == ErrGPGCheckFailed { fmt.Printf("Package failed GPG signature validation\n") } else { log.Fatal(err) }
Output: Package signed by 'CentOS-7 Key (CentOS 7 Official Signing Key) <security@centos.org>'
func MD5Check ¶
MD5Check validates the integrity of an rpm package file. The MD5 checksum is computed for the package payload and compared with the checksum specified in the package header.
If validation fails, ErrMD5CheckFailed is returned.
Example ¶
ExampleMD5Check validates a local rpm package named using the MD5 checksum value specified in the package header.
// open a rpm package for reading f, err := os.Open("testdata/centos-release-7-2.1511.el7.centos.2.10.x86_64.rpm") if err != nil { log.Fatal(err) } defer f.Close() // validate md5 checksum if err := MD5Check(f); err == nil { fmt.Printf("Package passed checksum validation\n") } else if err == ErrMD5CheckFailed { fmt.Printf("Package failed checksum validation\n") } else { log.Fatal(err) }
Output: Package passed checksum validation
func OpenKeyRing ¶
KeyRingFromFiles reads a openpgp.KeyRing from the given file paths which may then be used to validate GPG keys in rpm packages.
This function might typically be used to read all keys in /etc/pki/rpm-gpg.
func ReadKeyRing ¶
ReadKeyRing reads a openpgp.KeyRing from the given io.Reader which may then be used to validate GPG keys in rpm packages.
Types ¶
type Dependency ¶
type Dependency interface { Version // Version of the other package Name() string // Name of the other package Flags() int // See the DepFlag constants }
Dependency is an interface which represents a relationship between two packages. It might indicate that one package requires, conflicts with, obsoletes or provides another package.
Dependency implements the Version interface and so may be used when comparing versions.
type FileInfo ¶
type FileInfo struct {
// contains filtered or unexported fields
}
A FileInfo describes a file in an rpm package.
FileInfo implements the os.FileInfo interface.
type GPGSignature ¶
type GPGSignature []byte
GPGSignature is the raw byte representation of a package's signature.
func (GPGSignature) String ¶
func (b GPGSignature) String() string
type Lead ¶
type Lead struct { VersionMajor int VersionMinor int Name string Type int Architecture int OperatingSystem int SignatureType int }
Lead is the deprecated lead section of an rpm file which is used in legacy rpm versions to store package metadata.
type Package ¶
A Package is an rpm package file.
func Open ¶
Open opens an rpm package from the file system.
Once the package headers are read, the underlying reader is closed and cannot be used to read the package payload. To read the package payload, open the package with os.Open and read the headers with Read. You may then use the same reader to read the payload.
func Read ¶
Read reads an rpm package from r.
When this function returns, the reader will be positioned at the start of the package payload. Use Package.PayloadFormat and Package.PayloadCompression to determine how to decompress and unarchive the payload.
func (*Package) Architecture ¶
func (*Package) ArchiveSize ¶
ArchiveSize specifies the size of the archived payload of the package in bytes.
func (*Package) Conflicts ¶
func (c *Package) Conflicts() []Dependency
func (*Package) Description ¶
func (*Package) Distribution ¶
func (*Package) Enhances ¶
func (c *Package) Enhances() []Dependency
func (*Package) Files ¶
Files returns file information for each file that is installed by this RPM package.
Example ¶
Lists all the files in an rpm package.
// open a package file pkg, err := Open("./testdata/epel-release-7-5.noarch.rpm") if err != nil { log.Fatal(err) } // list each file files := pkg.Files() fmt.Printf("total %v\n", len(files)) for _, fi := range files { fmt.Printf("%v %v %v %5v %v %v\n", fi.Mode().Perm(), fi.Owner(), fi.Group(), fi.Size(), fi.ModTime().UTC().Format("Jan 02 15:04"), fi.Name()) }
Output: total 7 -rw-r--r-- root root 1662 Nov 25 16:23 /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 -rw-r--r-- root root 1056 Nov 25 16:23 /etc/yum.repos.d/epel-testing.repo -rw-r--r-- root root 957 Nov 25 16:23 /etc/yum.repos.d/epel.repo -rw-r--r-- root root 41 Nov 25 16:23 /usr/lib/rpm/macros.d/macros.epel -rw-r--r-- root root 2813 Nov 25 16:23 /usr/lib/systemd/system-preset/90-epel.preset -rwxr-xr-x root root 4096 Nov 25 16:26 /usr/share/doc/epel-release-7 -rw-r--r-- root root 18385 Nov 25 16:23 /usr/share/doc/epel-release-7/GPL
func (*Package) GPGSignature ¶
func (c *Package) GPGSignature() GPGSignature
func (*Package) InstallTime ¶
func (*Package) Obsoletes ¶
func (c *Package) Obsoletes() []Dependency
func (*Package) OldFilenames ¶
func (*Package) OperatingSystem ¶
func (*Package) PayloadCompression ¶
PayloadCompression returns the name of the compression used for the package payload. Typically xz.
func (*Package) PayloadFormat ¶
PayloadFormat returns the name of the format used for the package payload. Typically cpio.
func (*Package) PostInstallScript ¶
func (*Package) PostUninstallScript ¶
func (*Package) PreInstallScript ¶
func (*Package) PreUninstallScript ¶
func (*Package) Provides ¶
func (c *Package) Provides() []Dependency
func (*Package) RPMVersion ¶
func (*Package) Recommends ¶
func (c *Package) Recommends() []Dependency
func (*Package) Requires ¶
func (c *Package) Requires() []Dependency
func (*Package) String ¶
String returns the package identifier in the form '[name]-[version]-[release].[architecture]'.
func (*Package) Suggests ¶
func (c *Package) Suggests() []Dependency
func (*Package) Supplements ¶
func (c *Package) Supplements() []Dependency
type PackageSlice ¶ added in v1.1.0
type PackageSlice []*Package
PackageSlice implements sort.Interface for a slice of packages. Packages are sorted lexically by name ascending and then by version descending. Version is evaluated first by epoch, then by version string, then by release.
func (PackageSlice) Len ¶ added in v1.1.0
func (x PackageSlice) Len() int
func (PackageSlice) Less ¶ added in v1.1.0
func (x PackageSlice) Less(i, j int) bool
func (PackageSlice) Sort ¶ added in v1.1.0
func (x PackageSlice) Sort()
Sort is a convenience method: x.Sort() calls sort.Sort(x).
func (PackageSlice) Swap ¶ added in v1.1.0
func (x PackageSlice) Swap(i, j int)
type Tag ¶
Tag is an rpm header entry and its associated data value. Once the data type is known, use the associated value method to retrieve the tag value.
All Tag methods will return their zero value if the underlying data type is a different type or if the tag is nil.
func (*Tag) Bytes ¶
Bytes returns a slice of bytes or nil if the index is not a byte slice value.
Use Bytes for all CHAR, INT8 and BIN data types.
func (*Tag) Int64 ¶
Int64 returns an int64 if the index is not a numerical value. All integer types are cast to int64.
Use Int64 for all INT16, INT32 and INT64 data types.
func (*Tag) Int64Slice ¶
Int64Slice returns a slice of int64s or nil if the index is not a numerical slice value. All integer types are cast to int64.
Use Int64Slice for all INT16, INT32 and INT64 data types.
func (*Tag) String ¶
String returns a string or an empty string if the index is not a string value.
Use String for all STRING, STRING_ARRAY and I18NSTRING data types.
This is not intended to implement fmt.Stringer. To format the tag using its identifier, use Tag.ID. To format the tag's value, use Tag.Value.
func (*Tag) StringSlice ¶
StringSlice returns a slice of strings or nil if the index is not a string slice value.
Use StringSlice for all STRING, STRING_ARRAY and I18NSTRING data types.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
cmd
|
|
rpmdump
rpmdump displays all headers and tags in rpm packages as a YAML document.
|
rpmdump displays all headers and tags in rpm packages as a YAML document. |
rpminfo
rpminfo displays package information, akin to rpm --info.
|
rpminfo displays package information, akin to rpm --info. |