// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. // // Contributor: // - Aaron Meihm ameihm@mozilla.com package scribe import ( "os/exec" "regexp" "strings" ) var pkgmgrInitialized bool var pkgmgrCache []pkgmgrInfo type pkgmgrResult struct { results []pkgmgrInfo } type pkgmgrInfo struct { name string version string pkgtype string arch string } // PackageInfo stores information from the system as returned by QueryPackages(). type PackageInfo struct { Name string `json:"name" yaml:"name"` // Package name. Version string `json:"version" yaml:"version"` // Package version. Type string `json:"type" yaml:"type"` // Package type. Arch string `json:"arch" yaml:"arch"` // Package architecture } // QueryPackages will query packages on the system, returning a slice of all // identified packages in PackageInfo form. func QueryPackages() []PackageInfo { ret := make([]PackageInfo, 0) for _, x := range getAllPackages().results { np := PackageInfo{} np.Name = x.name np.Version = x.version np.Type = x.pkgtype np.Arch = x.arch ret = append(ret, np) } return ret } func getPackage(name string, collectexp string) (ret pkgmgrResult) { ret.results = make([]pkgmgrInfo, 0) if !pkgmgrInitialized { pkgmgrInit() } debugPrint("getPackage(): looking for \"%v\"\n", name) for _, x := range pkgmgrCache { if collectexp == "" { if x.name != name { continue } } else { mtch, err := regexp.MatchString(collectexp, x.name) if err != nil || !mtch { continue } } debugPrint("getPackage(): found %v, %v, %v\n", x.name, x.version, x.pkgtype) ret.results = append(ret.results, x) } debugPrint("getPackage(): returning %v entries\n", len(ret.results)) return } func getAllPackages() pkgmgrResult { ret := pkgmgrResult{} ret.results = make([]pkgmgrInfo, 0) if !pkgmgrInitialized { pkgmgrInit() } for _, x := range pkgmgrCache { ret.results = append(ret.results, x) } return ret } func pkgmgrInit() { debugPrint("pkgmgrInit(): initializing package manager...\n") pkgmgrCache = make([]pkgmgrInfo, 0) if sRuntime.testHooks { pkgmgrCache = append(pkgmgrCache, testGetPackages()...) } else { pkgmgrCache = append(pkgmgrCache, rpmGetPackages()...) pkgmgrCache = append(pkgmgrCache, dpkgGetPackages()...) } pkgmgrInitialized = true debugPrint("pkgmgrInit(): initialized with %v packages\n", len(pkgmgrCache)) } func rpmGetPackages() []pkgmgrInfo { ret := make([]pkgmgrInfo, 0) c := exec.Command("rpm", "-qa", "--queryformat", "%{NAME} %{EVR} %{ARCH}\\n") buf, err := c.Output() if err != nil { return ret } slist := strings.Split(string(buf), "\n") for _, x := range slist { s := strings.Fields(x) if len(s) < 3 { continue } newpkg := pkgmgrInfo{} newpkg.name = s[0] newpkg.version = s[1] newpkg.arch = s[2] newpkg.pkgtype = "rpm" ret = append(ret, newpkg) } return ret } func dpkgGetPackages() []pkgmgrInfo { ret := make([]pkgmgrInfo, 0) c := exec.Command("dpkg", "-l") buf, err := c.Output() if err != nil { return nil } slist := strings.Split(string(buf), "\n") for _, x := range slist { s := strings.Fields(x) if len(s) < 4 { continue } // Only process packages that have been fully installed. if s[0] != "ii" { continue } newpkg := pkgmgrInfo{} newpkg.name = s[1] newpkg.version = s[2] newpkg.arch = s[3] newpkg.pkgtype = "dpkg" ret = append(ret, newpkg) } return ret } // Functions and data related to package tests var testPkgTable = []struct { name string ver string }{ {"openssl", "1.0.1e"}, {"bash", "4.3-11"}, {"upstart", "1.13.2"}, {"grub-common", "2.02-beta2"}, {"libbind", "1:9.9.5.dfsg-4.3"}, {"kernel", "2.6.32-504.12.2.el6.x86_64"}, {"kernel", "2.6.32-573.8.1.el6.x86_64"}, } func testGetPackages() []pkgmgrInfo { ret := make([]pkgmgrInfo, 0) for _, x := range testPkgTable { newpkg := pkgmgrInfo{} newpkg.name = x.name newpkg.version = x.ver newpkg.pkgtype = "test" ret = append(ret, newpkg) } return ret }