[csw-devel] SF.net SVN: gar:[7727] csw/mgar/gar/v2-checkpkg/bin/checkpkg.d
wahwah at users.sourceforge.net
wahwah at users.sourceforge.net
Thu Dec 24 00:44:47 CET 2009
Revision: 7727
http://gar.svn.sourceforge.net/gar/?rev=7727&view=rev
Author: wahwah
Date: 2009-12-23 23:44:47 +0000 (Wed, 23 Dec 2009)
Log Message:
-----------
checkpkg.d: analyzing .so dependencies of single packages passes the smoke test (this time for real)
Modified Paths:
--------------
csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg-libs.py
csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg.py
Added Paths:
-----------
csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg_test.py
Property Changed:
----------------
csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg-libs.py
Modified: csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg-libs.py
===================================================================
--- csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg-libs.py 2009-12-23 23:40:15 UTC (rev 7726)
+++ csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg-libs.py 2009-12-23 23:44:47 UTC (rev 7727)
@@ -5,12 +5,198 @@
# A check for dependencies between shared libraries.
import checkpkg
+import os
import os.path
+import copy
+import re
+import subprocess
+import logging
+DUMP_BIN = "/usr/ccs/bin/dump"
+NEEDED_SONAMES = "needed sonames"
+RUNPATH = "runpath"
+
def main():
+ logging.basicConfig(level=logging.DEBUG)
options, args = checkpkg.GetOptions()
- pkgpath = os.path.join(options.extractdir, options.pkgname)
+ checker = checkpkg.CheckpkgBase(options.extractdir, options.pkgname)
+ binaries = checker.ListBinaries()
+ ws_re = re.compile(r"\s+")
+ # if [[ "$goodarch" = "yes" ]] ; then
+ # # man ld.so.1 for more info on this hack
+ # export LD_NOAUXFLTR=1
+ #
+ # listbinaries $EXTRACTDIR/$pkgname >$EXTRACTDIR/elflist
+ # # have to do this for ldd to work. arrg.
+ # if [ -s "$EXTRACTDIR/elflist" ] ; then
+ # chmod 0755 `cat $EXTRACTDIR/elflist`
+ #
+ # cat $EXTRACTDIR/elflist| xargs dump -Lv |nawk '$2=="NEEDED"{print $3}' |
+ # sort -u | egrep -v $EXTRACTDIR >$EXTRACTDIR/liblist
+ #
+ #
+ #
+ # print libraries used are:
+ # cat $EXTRACTDIR/liblist
+ # print "cross-referencing with depend file (May take a while)"
+ # else
+ # print No dynamic libraries in the package
+ # fi
+ # fi
+
+ env = copy.copy(os.environ)
+ env["LD_NOAUXFLTR"] = "1"
+ binaries_by_name = {}
+ # Assembling a data structure with the data about binaries.
+ # {
+ # <binary1 name>: {NEEDED_SONAMES: [...],
+ # RUNPATH: [...]},
+ # <binary2 name>: ...,
+ # ...
+ # }
+ #
+ for binary in binaries:
+ binary_base_name = binary.split("/")[-1]
+ if binary_base_name not in binaries_by_name:
+ binaries_by_name[binary_base_name] = {}
+ binary_data = binaries_by_name[binary_base_name]
+ args = [DUMP_BIN, "-Lv", binary]
+ dump_proc = subprocess.Popen(args, stdout=subprocess.PIPE)
+ stdout, stderr = dump_proc.communicate()
+ ret = dump_proc.wait()
+ for line in stdout.splitlines():
+ fields = re.split(ws_re, line)
+ logging.debug("%s says: %s", DUMP_BIN, fields)
+ if len(fields) < 3:
+ continue
+ if fields[1] == "NEEDED":
+ if NEEDED_SONAMES not in binary_data:
+ binary_data[NEEDED_SONAMES] = []
+ binary_data[NEEDED_SONAMES].append(fields[2])
+ elif fields[1] == "RUNPATH":
+ if RUNPATH not in binary_data:
+ binary_data[RUNPATH] = []
+ binary_data[RUNPATH].extend(fields[2].split(":"))
+ # Adding the default runtime path search option.
+ binary_data[RUNPATH].append("/usr/lib")
+ print binaries_by_name
+ # Building indexes
+ runpath_by_needed_soname = {}
+ # {"foo.so": ["/opt/csw/lib/gcc4", "/opt/csw/lib", ...],
+ # ...
+ # }
+ needed_sonames = set()
+ binaries_by_soname = {}
+ for binary_name, data in binaries_by_name.iteritems():
+ for soname in data[NEEDED_SONAMES]:
+ needed_sonames.add(soname)
+ if soname not in runpath_by_needed_soname:
+ runpath_by_needed_soname[soname] = []
+ runpath_by_needed_soname[soname].extend(data[RUNPATH])
+ if soname not in binaries_by_soname:
+ binaries_by_soname[soname] = []
+ binaries_by_soname[soname].append(binary_name)
+
+ pkgmap = checkpkg.SystemPkgmap()
+ paths_by_soname = pkgmap.paths_by_soname
+
+ logging.debug("Determining soname-file relationships.")
+ # lines by soname is an equivalent of $EXTRACTDIR/shortcatalog
+ lines_by_soname = {}
+ for soname in needed_sonames:
+ if soname in paths_by_soname:
+ logging.debug("%s found", repr(soname))
+ # Finding the first matching path
+ for runpath in runpath_by_needed_soname[soname]:
+ if runpath in paths_by_soname[soname]:
+ logging.debug("%s found in %s", runpath, paths_by_soname[soname])
+ logging.debug("line found: %s", repr(paths_by_soname[soname][runpath]))
+ lines_by_soname[soname] = paths_by_soname[soname][runpath]
+ break
+ else:
+ logging.debug("%s not found in the soname list!", soname)
+ for soname in needed_sonames:
+ if soname in binaries:
+ print "%s is provided by the package itself" % soname
+ elif soname in lines_by_soname:
+ print ("%s is required by %s and provided by %s"
+ % (soname,
+ binaries_by_soname[soname],
+ repr(lines_by_soname[soname])))
+ else:
+ print ("%s is required by %s, but we don't know what provides it."
+ % (soname, binaries_by_soname[soname]))
+
+ # for lib in `cat $EXTRACTDIR/liblist` ; do
+ # grep "[/=]$lib[ =]" $EXTRACTDIR/$pkgname/pkgmap
+ # if [[ $? -eq 0 ]] ; then
+ # echo $lib provided by package itself
+ # continue
+ # else
+ # grep "[/=]$lib[ =]" $SETLIBS
+ # if [[ $? -eq 0 ]]; then
+ # echo "$lib provided by package set being evaluated."
+ # continue
+ # fi
+ # fi
+ #
+ # libpkg=`grep /$lib $EXTRACTDIR/shortcatalog |
+ # sed 's/^.* \([^ ]*\)$/\1/' |sort -u`
+ #
+ # if [[ -z "$libpkg" ]] ; then
+ # echo "$lib $pkgname" >> $SETLIBS.missing
+ # print Cannot find package providing $lib. Storing for delayed validation.
+ # else
+ # print $libpkg | fmt -1 >>$EXTRACTDIR/libpkgs
+ # fi
+ # done
+ #
+ # sort -u $EXTRACTDIR/libpkgs >$EXTRACTDIR/libpkgs.x
+ # mv $EXTRACTDIR/libpkgs.x $EXTRACTDIR/libpkgs
+ #
+ # diff $EXTRACTDIR/deppkgs $EXTRACTDIR/libpkgs >/dev/null
+ # if [[ $? -ne 0 ]] ; then
+ # print SUGGESTION: you may want to add some or all of the following as depends:
+ # print ' (Feel free to ignore SUNW or SPRO packages)'
+ # diff $EXTRACTDIR/deppkgs $EXTRACTDIR/libpkgs | fgrep '>'
+ # fi
+ #
+ #
+ #
+ # if [[ "$basedir" != "" ]] ; then
+ # print
+ # if [[ -f $EXTRACTDIR/elflist ]] ; then
+ # print "Checking relocation ability..."
+ # xargs strings < $EXTRACTDIR/elflist| grep /opt/csw
+ # if [[ $? -eq 0 ]] ; then
+ # errmsg package build as relocatable, but binaries have hardcoded /opt/csw paths in them
+ # else
+ # print trivial check passed
+ # fi
+ # else
+ # echo No relocation check done for non-binary relocatable package.
+ # fi
+ # fi
+ #
+ # ...
+ #
+ # if [ -s $SETLIBS.missing ]; then
+ # print "Doing late evaluations of package library dependencies."
+ # while read ldep; do
+ # lib=`echo $ldep | nawk '{print $1}'`
+ # [ "$lib" = "libm.so.2" ] && continue
+ # pkg=`echo $ldep | nawk '{print $2}'`
+ # /usr/bin/grep "[/=]$lib[ =]" $SETLIBS >/dev/null
+ # if [ $? -ne 0 ]; then
+ # errmsg "Couldn't find a package providing $lib"
+ # else
+ # print "A package in the set being evaluated provides $lib"
+ # fi
+ # done < $SETLIBS.missing
+ # fi
+
+
if __name__ == '__main__':
- main()
+ main()
Property changes on: csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg-libs.py
___________________________________________________________________
Added: svn:executable
+ *
Modified: csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg.py
===================================================================
--- csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg.py 2009-12-23 23:40:15 UTC (rev 7726)
+++ csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg.py 2009-12-23 23:44:47 UTC (rev 7727)
@@ -1,22 +1,125 @@
-# This is a checkpkg library, common for all checkpkg tests written in Python.
+# $Id$
+#
+# This is the checkpkg library, common for all checkpkg tests written in
+# Python.
import optparse
+import os
+import os.path
+import logging
+import subprocess
+import cPickle
+import re
+SYSTEM_PKGMAP = "/var/sadm/install/contents"
+
class Error(Exception):
pass
+
class ConfigurationError(Error):
pass
+
+class PackageError(Error):
+ pass
+
+
def GetOptions():
parser = optparse.OptionParser()
parser.add_option("-e", dest="extractdir",
help="The directory into which the package has been extracted")
parser.add_option("-p", dest="pkgname",
help="The pkgname, e.g. CSWfoo")
+ parser.add_option("-d", "--debug", dest="debug",
+ default=False, action="store_true",
+ help="Turn on debugging messages")
(options, args) = parser.parse_args()
if not options.extractdir:
raise ConfigurationError("ERROR: -e option is missing.")
if not options.pkgname:
raise ConfigurationError("ERROR: -p option is missing.")
return options, args
+
+
+class CheckpkgBase(object):
+
+ def __init__(self, extractdir, pkgname):
+ self.extractdir = extractdir
+ self.pkgname = pkgname
+ self.pkgpath = os.path.join(self.extractdir, self.pkgname)
+
+ def ListBinaries(self):
+ # #########################################
+ # # find all executables and dynamic libs,and list their filenames.
+ # listbinaries() {
+ # if [ ! -d $1 ] ; then
+ # print errmsg $1 not a directory
+ # rm -rf $EXTRACTDIR
+ # exit 1
+ # fi
+ #
+ # find $1 -print | xargs file |grep ELF |nawk -F: '{print $1}'
+ # }
+ find_tmpl = "find %s -print | xargs file | grep ELF | nawk -F: '{print $1}'"
+ if not os.path.isdir(self.pkgpath):
+ raise PackageError("%s does not exist or is not a directory"
+ % self.pkgpath)
+ find_proc = subprocess.Popen(find_tmpl % self.pkgpath,
+ shell=True, stdout=subprocess.PIPE)
+ stdout, stderr = find_proc.communicate()
+ ret = find_proc.wait()
+ if ret:
+ logging.error("The find command returned an error.")
+ return stdout.splitlines()
+
+class SystemPkgmap(object):
+ """A class to hold and manipulate the /var/sadm/install/contents file."""
+
+ PICKLE_NAME = "var-sadm-install-contents.pickle"
+ WS_RE = re.compile(r"\s+")
+ def __init__(self):
+ """There is no need to re-parse it each time.
+
+ Read it slowly the first time and cache it for later."""
+ self.checkpkg_dir = os.path.join(os.environ["HOME"], ".checkpkg")
+ self.pickle_path = os.path.join(self.checkpkg_dir, self.PICKLE_NAME)
+ if os.path.exists(self.pickle_path):
+ logging.debug("Unpickling %s, please wait.", self.pickle_path)
+ pickle_fd = open(self.pickle_path, "r")
+ self.paths_by_soname = cPickle.load(pickle_fd)
+ pickle_fd.close()
+ else:
+ # The original checkpkg code to port is in the comments.
+ #
+ # egrep -v 'SUNWbcp|SUNWowbcp|SUNWucb' /var/sadm/install/contents |
+ # fgrep -f $EXTRACTDIR/liblist >$EXTRACTDIR/shortcatalog
+ stop_pkgs = ["SUNWbcp", "SUNWowbcp", "SUNWucb"]
+ system_pkgmap_fd = open(SYSTEM_PKGMAP, "r")
+
+ stop_re = re.compile("(%s)" % "|".join(stop_pkgs))
+
+ # Creating a data structure:
+ # soname - {<path1>: <line1>, <path2>: <line2>, ...}
+ logging.debug("Building in-memory data structure for the %s file",
+ SYSTEM_PKGMAP)
+ paths_by_soname = {}
+ for line in system_pkgmap_fd:
+ if stop_re.search(line):
+ continue
+ fields = re.split(self.WS_RE, line)
+ pkgmap_entry_path = fields[0].split("=")[0]
+ pkgmap_entry_dir, pkgmap_entry_base_name = os.path.split(pkgmap_entry_path)
+ if pkgmap_entry_base_name not in paths_by_soname:
+ paths_by_soname[pkgmap_entry_base_name] = {}
+ paths_by_soname[pkgmap_entry_base_name][pkgmap_entry_dir] = line
+ logging.debug("The data structure contains %s files",
+ len(paths_by_soname))
+ self.paths_by_soname = paths_by_soname
+ if not os.path.exists(self.checkpkg_dir):
+ logging.debug("Creating %s", self.checkpkg_dir)
+ os.mkdir(self.checkpkg_dir)
+ logging.debug("Pickling to %s", self.pickle_path)
+ pickle_fd = open(self.pickle_path, "w")
+ cPickle.dump(self.paths_by_soname, pickle_fd)
+ pickle_fd.close()
Added: csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg_test.py
===================================================================
--- csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg_test.py (rev 0)
+++ csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg_test.py 2009-12-23 23:44:47 UTC (rev 7727)
@@ -0,0 +1,8 @@
+#!/opt/csw/bin/python2.6
+
+import unittest
+
+
+
+if __name__ == '__main__':
+ unittest.main()
Property changes on: csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg_test.py
___________________________________________________________________
Added: svn:keywords
+ Id
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the devel
mailing list