1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
package version
import (
"bytes"
"fmt"
"os/exec"
"strings"
"github.com/containers/storage/pkg/fileutils"
)
const (
UnknownPackage = "Unknown"
)
// Note: This function is copied from containers/podman libpod/util.go
// Please see https://github.com/containers/common/pull/1460
func queryPackageVersion(cmdArg ...string) string {
err := fileutils.Exists(cmdArg[0])
if err != nil {
return ""
}
output := UnknownPackage
if 1 < len(cmdArg) {
cmd := exec.Command(cmdArg[0], cmdArg[1:]...)
if outp, err := cmd.Output(); err == nil {
output = string(outp)
switch cmdArg[0] {
case "/usr/bin/dlocate":
// can return multiple matches
l := strings.Split(output, "\n")
output = l[0]
r := strings.Split(output, ": ")
regexpFormat := `^..\s` + r[0] + `\s`
cmd = exec.Command(cmdArg[0], "-P", regexpFormat, "-l")
cmd.Env = []string{"COLUMNS=160"} // show entire value
// dlocate always returns exit code 1 for list command
if outp, _ = cmd.Output(); len(outp) > 0 {
lines := strings.Split(string(outp), "\n")
if len(lines) > 1 {
line := lines[len(lines)-2] // trailing newline
f := strings.Fields(line)
if len(f) >= 2 {
return f[1] + "_" + f[2]
}
}
}
case "/usr/bin/dpkg":
r := strings.Split(output, ": ")
queryFormat := `${Package}_${Version}_${Architecture}`
cmd = exec.Command("/usr/bin/dpkg-query", "-f", queryFormat, "-W", r[0])
if outp, err := cmd.Output(); err == nil {
output = string(outp)
}
case "/usr/bin/pacman":
pkg := strings.Trim(output, "\n")
cmd = exec.Command(cmdArg[0], "-Q", "--", pkg)
if outp, err := cmd.Output(); err == nil {
output = strings.ReplaceAll(string(outp), " ", "-")
}
case "/sbin/apk":
prefix := cmdArg[len(cmdArg)-1] + " is owned by "
output = strings.Replace(output, prefix, "", 1)
}
}
}
return strings.Trim(output, "\n")
}
// Note: This function is copied from containers/podman libpod/util.go
// Please see https://github.com/containers/common/pull/1460
func Package(program string) string { // program is full path
err := fileutils.Exists(program)
if err != nil {
return UnknownPackage
}
type Packager struct {
Format string
Command []string
}
packagers := []Packager{
{"rpm", []string{"/usr/bin/rpm", "-q", "-f"}},
{"deb", []string{"/usr/bin/dlocate", "-F"}}, // Debian, Ubuntu (quick)
{"deb", []string{"/usr/bin/dpkg", "-S"}}, // Debian, Ubuntu (slow)
{"pacman", []string{"/usr/bin/pacman", "-Qoq"}}, // Arch
{"gentoo", []string{"/usr/bin/qfile", "-qv"}}, // Gentoo (quick)
{"gentoo", []string{"/usr/bin/equery", "b"}}, // Gentoo (slow)
{"apk", []string{"/sbin/apk", "info", "-W"}}, // Alpine
{"pkg", []string{"/usr/local/sbin/pkg", "which", "-q"}}, // FreeBSD
}
lastformat := ""
for _, packager := range packagers {
if packager.Format == lastformat {
continue
}
cmd := packager.Command
cmd = append(cmd, program)
if out := queryPackageVersion(cmd...); out != UnknownPackage {
if out == "" {
continue
}
return out
}
lastformat = packager.Format
}
return UnknownPackage
}
// Note: This function is copied from containers/podman libpod/util.go
// Please see https://github.com/containers/common/pull/1460
func Program(name string) (string, error) {
return program(name, false)
}
func ProgramDnsname(name string) (string, error) {
return program(name, true)
}
func program(program string, dnsname bool) (string, error) {
cmd := exec.Command(program, "--version")
var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("`%v --version` failed: %v %v (%v)", program, stderr.String(), stdout.String(), err)
}
output := strings.TrimSuffix(stdout.String(), "\n")
// dnsname --version returns the information to stderr
if dnsname {
output = strings.TrimSuffix(stderr.String(), "\n")
}
return output, nil
}
|