#!/usr/bin/env python ## ## This script will scan all of the packages in PSTAGE_DIR (or argv[1]) ## in search of packages which install files outside of their native sysroot ## import os, sys, tarfile, shutil import subprocess as sub logf = "" pcount = 0 ecount = 0 def main(): """Generate a list of pstage packages and scan them for badness""" package_list = [] try: path = sysv.arg[1] except: # Assume pstage is a child of tmp, Poky's default tmpdir = None sub.Popen(["bitbake", "-e"], stdout=sub.PIPE,stderr=sub.PIPE) err, out = p.communicate() if (!out): print("bitbake not in your environment, try pstage-scanner /some/path/to/pstage") exit for line in out: if line.find("PSTAGE_DIR=") != -1: tmpdir = line.partition("=")[2].strip("\"") break if len(path) < 1 or not os.path.exists(path): print ("No path defined and bitbake not in your environment, try pstage-scanner /some/path/to/pstage") exit global logf try: logf = sys.argv[2] except: logf = os.path.join(path, "pstage-scanner.log") ## Create a working directory tempdir = os.path.join(path, "tmp") os.mkdir(tempdir) ## Iterate each child of the target directory looking for .ipk files and ## building a list of files to process for root, dirs, files in os.walk(path): for d in dirs: for f in os.listdir(os.path.join(root,d)): if os.path.splitext(f)[1] == ".ipk" and f.find("native") == -1 and f.find("cross") == -1: package_list.append(os.path.join(root,d,f)) ## Next we iterate our built list of files and process each package for pkg in package_list: tmp = os.path.join(tempdir, os.path.splitext(os.path.split(pkg)[1])[0]) os.mkdir(tmp) scan_package(pkg, tmp) ## Tidy up working directory shutil.rmtree(tempdir) ## Report a summary log("Finished scanning packaged staging. Scanned %i packages with %i errors" % (pcount, ecount)) def scan_package(filepath, parentdir): """Helper method to do bookkeeping, passes all installable directories to scan_dir which does the actual scanning.""" os.chdir(parentdir) ## increment the package count, for the summary global pcount pcount += 1 ## An ipk file is an ar archive containing two gzipped tarball directories ## data.tar.gz is inflated to / and contains the actual files ## control.tar.gz is metadata and scripts for the package ## The archive also contains a file, debian binary, which is unused ## Python can't handle ar archives ootb. So we cheat and inflate with ## the ar program on the host sub.call(["ar", "x", filepath]) ## The things we care about are in data.tar.gz tgz = tarfile.open(os.path.join(parentdir, "data.tar.gz")) dest = os.path.join(parentdir, "inflate") os.mkdir(dest) tgz.extractall(dest) ## We want to know the target arch so that we can ensure the package is ## only installing into its target sysroot arch = os.path.splitext(os.path.basename(filepath))[0].split("_")[-1] if arch == "64": arch = "x86_64" ## The ignored list contains directories we don't care to scan ignored = ["pkgdata", "stamps", "deploy"] ## Scan the package for badness pname = os.path.split(filepath)[1] for di in os.listdir(dest): if di not in ignored: scan_dir(os.path.join(dest, di), arch, pname) def scan_dir (directory, arch, package_name): """Scan the contents of directory for things installing outside of native sysroot""" global ecount msg = "" head, tail = os.path.split(directory) if not tail == "sysroots": msg += "Tsk tsk, installing to " + tail + "\n" for d in os.listdir(directory): msg += "Installing %s in %s" % (d, tail) + "\n" ecount += 1 else: for d in os.listdir(directory): if not d.startswith(arch) and d.find("fixmepath") == -1: msg += "Tsk tsk, installing into non-native sysroot " + os.path.join(directory, d) ecount += 1 if len(msg) > 0: log("Scanning package " + package_name + "\n" + msg) def log (message): global logf logfile = open (logf, 'a+') logfile.write(message + "\n") print "LOG: " + message logfile.close() if __name__ == "__main__": main()