in vmassist/linux/vmassist.py [0:0]
def validateBin(binPathIn):
# usage: pass in a binary to check, the following will be determined
# - absolute path (dereference links)
# - provided by what package
# - what repo provides the package
# - version for the package or binary if possible
# output object:
# load up os-release into a dict for later reference
logger.info("Validating " + binPathIn)
# we need to store the passed value in case of exception with the dereferenced path
binPath=binPathIn
realBin=os.path.realpath(binPath)
if ( binPath != realBin ):
logger.info(f"Link found: {binPath} points to {realBin}, verify outputs if this returns empty data")
binPath=realBin
thisBin={"exe":binPathIn}
if (osrID == "debian"):
noPkg=False # extra exception flag, using pure try/excepts is difficult to follow
try:
# Find what package owns the binary
thisBin["pkg"]=subprocess.check_output("dpkg -S " + binPath, shell=True, stderr=subprocess.DEVNULL).decode().strip().split(":")[0]
except:
logger.info(f"issue validating {binPath}, reverting to original path: {binPathIn}")
try:
thisBin["pkg"]=subprocess.check_output("dpkg -S " + binPathIn, shell=True, stderr=subprocess.DEVNULL).decode().strip().split(":")[0]
except subprocess.CalledProcessError as e:
logger.info(f"All attempts to validate {binPathIn} have failed. Likely a rogue file: {e.output}")
noPkg=True
if not noPkg:
# find what repository the package came from
try:
aptOut=subprocess.check_output("apt-cache show --no-all-versions " + thisBin["pkg"] , shell=True, stderr=subprocess.DEVNULL).decode().strip()
thisBin["repo"]=re.search("Origin.*",aptOut).group()
except subprocess.CalledProcessError as e:
# we didn't get a match, probably a manual install (dkpg) or installed from source
logger.info(f"package {thisBin['pkg']} does not appear to have come from a repository")
thisBin["repo"]="no repo"
else:
# binary not found or may be source installed (no pkg)
thisBin["pkg"]=f"no file or owning pkg for {binPathIn}"
thisBin["repo"]="n/a"
elif ( osrID == "fedora"):
try:
rpm=subprocess.check_output("rpm -q --whatprovides " + binPath, shell=True, stderr=subprocess.DEVNULL).decode().strip()
thisBin["pkg"]=rpm
try:
# expand on this to make the call to 'dnf'
#dnfOut=subprocess.check_output("dnf info " + rpm, shell=True, stderr=subprocess.DEVNULL).decode().strip()
result=subprocess.run(["dnf","info",rpm], stdout=subprocess.PIPE, stderr=subprocess.PIPE,check=True)
except subprocess.CalledProcessError as e:
# we didn't get a match, probably a manual install (rpm), built from source, or a general DNF failure
thisBin["repo"]=f"repo search failed: {e.stderr.decode()}"
else:
dnfOut=result.stdout.decode().strip()
# Repo line should look like "From repo : [reponame]" so clean it up
thisBin["repo"]=re.search("From repo.*",dnfOut).group().strip().split(":")[1].strip()
except subprocess.CalledProcessError as e:
thisBin["pkg"]=f"no file or owning pkg: {e.output}"
thisBin["repo"]="n/a"
elif ( osrID == "suse"):
try:
rpm=subprocess.check_output('rpm -q --queryformat %{NAME} --whatprovides ' + binPath, shell=True, stderr=subprocess.DEVNULL).decode()
thisBin["pkg"]=rpm
try:
# options:
zyppOut=subprocess.check_output("zypper --quiet --no-refresh info " + rpm, shell=True, stderr=subprocess.DEVNULL).decode().strip()
thisBin["repo"]=re.search("Repository.*",zyppOut).group().split(":")[1].strip()
except:
# we didn't get a match, probably a manual install (rpm) or from source
thisBin["repo"]="not from a repo"
except subprocess.CalledProcessError as e:
thisBin["pkg"]="no file or owning pkg: " + e
thisBin["repo"]="n/a"
elif ( osrID == "mariner" or osrID == "azurelinux"):
try:
rpm=subprocess.check_output('rpm -q --queryformat %{NAME} --whatprovides ' + binPath, shell=True).decode()
thisBin["pkg"]=rpm
try:
# options:
zyppOut=subprocess.check_output("tdnf --installed info " + rpm, shell=True).decode().strip()
thisBin["repo"]=re.search("Repo.*",zyppOut).group().split(":")[1].strip()
except:
# we didn't get a match, probably a manual install (rpm) or from source
thisBin["repo"]="not from a repo"
except subprocess.CalledProcessError as e:
thisBin["pkg"]="no file or owning pkg: " + e
thisBin["repo"]="n/a"
else:
print("Unable to determine OS family from os-release")
thisBin["pkg"]="packaging system unknown"
thisBin["repo"]="n/a"
logString = binPath + " owned by package '" + thisBin["pkg"] + "' from repo '" + thisBin["repo"] + "'"
logger.info(logString)
bins[binPathIn]=thisBin