aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/pstage-scanner
blob: 9234912581b6b5c40f264df7d9167d7aa6595e2e (plain)
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
#!/usr/bin/env python

##
## This script will scan all of the packages in ${OEROOT}/pstage (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 = []

    ## First we walk the pstage directory, let's assume we're running from
    ## a sibling of pstage (i.e. scripts) if no path defined
    try:
        path = sysv.arg[1]
    except:
        path = os.path.join(os.environ.get("OEROOT"), "pstage")

    if len(path) < 1 or not os.path.exists(path):
        path = os.path.join(os.environ.get("OEROOT"), "pstage")
    
    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()