[csw-devel] SF.net SVN: gar:[10479] csw/mgar/gar/v2/lib/python
wahwah at users.sourceforge.net
wahwah at users.sourceforge.net
Fri Jul 9 11:50:35 CEST 2010
Revision: 10479
http://gar.svn.sourceforge.net/gar/?rev=10479&view=rev
Author: wahwah
Date: 2010-07-09 09:50:35 +0000 (Fri, 09 Jul 2010)
Log Message:
-----------
mGAR checkpkg: support for $ORIGIN in rpath, one-time message support in the messenger class.
Modified Paths:
--------------
csw/mgar/gar/v2/lib/python/checkpkg.py
csw/mgar/gar/v2/lib/python/checkpkg_test.py
csw/mgar/gar/v2/lib/python/dependency_checks.py
csw/mgar/gar/v2/lib/python/package_checks.py
csw/mgar/gar/v2/lib/python/package_checks_test.py
Modified: csw/mgar/gar/v2/lib/python/checkpkg.py
===================================================================
--- csw/mgar/gar/v2/lib/python/checkpkg.py 2010-07-09 01:27:36 UTC (rev 10478)
+++ csw/mgar/gar/v2/lib/python/checkpkg.py 2010-07-09 09:50:35 UTC (rev 10479)
@@ -18,6 +18,7 @@
import socket
import sqlite3
import sqlobject
+import time
from sqlobject import sqlbuilder
import subprocess
import textwrap
@@ -523,8 +524,10 @@
return schema_on_disk
def IsDatabaseUpToDate(self):
- f_mtime = self.GetFileMtime()
- d_mtime = self.GetDatabaseMtime()
+ f_mtime_epoch = self.GetFileMtime()
+ d_mtime_epoch = self.GetDatabaseMtime()
+ f_mtime = time.gmtime(int(f_mtime_epoch))
+ d_mtime = time.gmtime(int(d_mtime_epoch))
logging.debug("IsDatabaseUpToDate: f_mtime %s, d_time: %s", f_mtime, d_mtime)
# Rounding up to integer seconds. There is a race condition:
# pkgadd finishes at 100.1
@@ -532,7 +535,7 @@
# new pkgadd runs and finishes at 100.3
# subsequent checkpkg runs won't pick up the last change.
# I don't expect pkgadd to run under 1s.
- fresh = int(f_mtime) <= int(d_mtime)
+ fresh = f_mtime <= d_mtime
good_version = self.GetDatabaseSchemaVersion() >= DB_SCHEMA_VERSION
logging.debug("IsDatabaseUpToDate: good_version=%s, fresh=%s",
repr(good_version), repr(fresh))
@@ -562,21 +565,45 @@
"""
def __init__(self):
self.runpath_expand_cache = {}
+ self.runpath_origin_expand_cache = {}
self.symlink_expand_cache = {}
self.symlink64_cache = {}
self.runpath_sanitize_cache = {}
- def ExpandRunpath(self, runpath, isalist):
+ def ExpandRunpath(self, runpath, isalist, binary_path):
+ """Expands a signle runpath element.
+
+ Args:
+ runpath: e.g. "/opt/csw/lib/$ISALIST"
+ isalist: isalist elements
+ binary_path: Necessary to expand $ORIGIN
+ """
# TODO: Implement $ORIGIN support
# Probably not here as it would make caching unusable.
key = (runpath, tuple(isalist))
if key not in self.runpath_expand_cache:
- # Emulating $ISALIST expansion
+ origin_present = False
+ # Emulating $ISALIST and $ORIGIN expansion
+ if '$ORIGIN' in runpath:
+ origin_present = True
+ if origin_present:
+ key_o = (runpath, tuple(isalist), binary_path)
+ if key_o in self.runpath_origin_expand_cache:
+ return self.runpath_origin_expand_cache[key_o]
+ else:
+ if not binary_path.startswith("/"):
+ binary_path = "/" + binary_path
+ runpath = runpath.replace('$ORIGIN', binary_path)
if '$ISALIST' in runpath:
expanded_list = [runpath.replace('$ISALIST', isa) for isa in isalist]
else:
expanded_list = [runpath]
- self.runpath_expand_cache[key] = expanded_list
+ expanded_list = [os.path.abspath(p) for p in expanded_list]
+ if not origin_present:
+ self.runpath_expand_cache[key] = expanded_list
+ else:
+ self.runpath_origin_expand_cache[key_o] = expanded_list
+ return self.runpath_origin_expand_cache[key_o]
return self.runpath_expand_cache[key]
def ExpandSymlink(self, symlink, target, input_path):
@@ -624,7 +651,7 @@
return self.runpath_sanitize_cache[runpath]
- def ResolveSoname(self, runpath, soname, isalist, path_list):
+ def ResolveSoname(self, runpath_list, soname, isalist, path_list, binary_path):
"""Emulates ldd behavior, minimal implementation.
runpath: e.g. ["/opt/csw/lib/$ISALIST", "/usr/lib"]
@@ -635,9 +662,6 @@
The function returns the one path.
"""
- runpath = self.SanitizeRunpath(runpath)
- runpath_list = self.ExpandRunpath(runpath, isalist)
- runpath_list = self.Emulate64BitSymlinks(runpath_list)
# Emulating the install time symlinks, for instance, if the prototype contains
# /opt/csw/lib/i386/foo.so.0 and /opt/csw/lib/i386 is a symlink to ".",
# the shared library ends up in /opt/csw/lib/foo.so.0 and should be
@@ -862,11 +886,16 @@
"""Class responsible for passing messages from checks to the user."""
def __init__(self):
self.messages = []
+ self.one_time_messages = {}
self.gar_lines = []
def Message(self, m):
self.messages.append(m)
+ def OneTimeMessage(self, key, m):
+ if key not in self.one_time_messages:
+ self.one_time_messages[key] = m
+
def SuggestGarLine(self, m):
self.gar_lines.append(m)
@@ -934,7 +963,8 @@
function(pkgs_data, check_interface, logger=logger, messenger=messenger)
if check_interface.errors:
errors = self.SetErrorsToDict(check_interface.errors, errors)
- return errors, messenger.messages, messenger.gar_lines
+ messages = messenger.messages + messenger.one_time_messages.values()
+ return errors, messages, messenger.gar_lines
def Run(self):
self._AutoregisterChecks()
Modified: csw/mgar/gar/v2/lib/python/checkpkg_test.py
===================================================================
--- csw/mgar/gar/v2/lib/python/checkpkg_test.py 2010-07-09 01:27:36 UTC (rev 10478)
+++ csw/mgar/gar/v2/lib/python/checkpkg_test.py 2010-07-09 09:50:35 UTC (rev 10479)
@@ -45,15 +45,59 @@
isalist = ["foo", "bar"]
runpath = "/opt/csw/lib/$ISALIST"
expected = ["/opt/csw/lib/foo", "/opt/csw/lib/bar"]
- self.assertEquals(expected, self.e.ExpandRunpath(runpath, isalist))
+ bin_path = "opt/csw/lib"
+ self.assertEquals(expected, self.e.ExpandRunpath(runpath, isalist, bin_path))
def testExpandRunpath_2(self):
isalist = ["foo", "bar"]
runpath = "/opt/csw/mysql5/lib/$ISALIST/mysql"
expected = ["/opt/csw/mysql5/lib/foo/mysql",
"/opt/csw/mysql5/lib/bar/mysql"]
- self.assertEquals(expected, self.e.ExpandRunpath(runpath, isalist))
+ bin_path = "opt/csw/lib"
+ self.assertEquals(expected, self.e.ExpandRunpath(runpath, isalist, bin_path))
+ def testExpandRunpath_OriginSimple(self):
+ isalist = ()
+ runpath = "$ORIGIN"
+ expected = ["/opt/csw/lib"]
+ bin_path = "opt/csw/lib"
+ self.assertEquals(expected, self.e.ExpandRunpath(runpath, isalist, bin_path))
+
+ def testExpandRunpath_OriginDots(self):
+ isalist = ()
+ runpath = "$ORIGIN/.."
+ expected = ["/opt/csw/lib"]
+ bin_path = "opt/csw/lib/subdir"
+ self.assertEquals(expected, self.e.ExpandRunpath(runpath, isalist, bin_path))
+
+ def testExpandRunpath_Caching(self):
+ """Make sure that the cache doesn't mess it up.
+
+ Two invocations, where the only difference is the binary path.
+ """
+ isalist = ()
+ runpath = "/opt/csw/lib/foo"
+ expected = ["/opt/csw/lib/foo"]
+ bin_path = "opt/csw/lib"
+ self.assertEquals(expected, self.e.ExpandRunpath(runpath, isalist, bin_path))
+ expected = ["/opt/csw/lib/foo"]
+ bin_path = "/opt/csw/lib/foo"
+ self.assertEquals(expected, self.e.ExpandRunpath(runpath, isalist, bin_path))
+
+ def testExpandRunpath_OriginCaching(self):
+ """Make sure that the cache doesn't mess it up.
+
+ Two invocations, where the only difference is the binary path.
+ """
+ isalist = ()
+ runpath = "$ORIGIN"
+ expected = ["/opt/csw/lib"]
+ bin_path = "opt/csw/lib"
+ self.assertEquals(expected, self.e.ExpandRunpath(runpath, isalist, bin_path))
+ expected = ["/opt/csw/foo/lib"]
+ bin_path = "/opt/csw/foo/lib"
+ self.assertEquals(expected, self.e.ExpandRunpath(runpath, isalist, bin_path))
+
def testEmulate64BitSymlinks_1(self):
runpath_list = ["/opt/csw/mysql5/lib/foo/mysql/64"]
expected = "/opt/csw/mysql5/lib/foo/mysql/amd64"
@@ -130,14 +174,14 @@
'RPATH set': True,
'RUNPATH RPATH the same': True,
'RUNPATH set': True,
- 'needed sonames': ['librt.so.1',
+ 'needed sonames': ('librt.so.1',
'libresolv.so.2',
'libc.so.1',
'libgen.so.1',
'libsocket.so.1',
'libnsl.so.1',
'libm.so.1',
- 'libz.so.1'],
+ 'libz.so.1'),
'runpath': ('/opt/csw/lib/$ISALIST',
'/opt/csw/lib',
'/opt/csw/mysql5/lib/$ISALIST',
@@ -159,14 +203,14 @@
'RPATH set': True,
'RUNPATH RPATH the same': False,
'RUNPATH set': False,
- 'needed sonames': ['librt.so.1',
+ 'needed sonames': ('librt.so.1',
'libresolv.so.2',
'libc.so.1',
'libgen.so.1',
'libsocket.so.1',
'libnsl.so.1',
'libm.so.1',
- 'libz.so.1'],
+ 'libz.so.1'),
'runpath': ('/opt/csw/lib/$ISALIST',
'/opt/csw/lib',
'/opt/csw/mysql5/lib/$ISALIST',
Modified: csw/mgar/gar/v2/lib/python/dependency_checks.py
===================================================================
--- csw/mgar/gar/v2/lib/python/dependency_checks.py 2010-07-09 01:27:36 UTC (rev 10478)
+++ csw/mgar/gar/v2/lib/python/dependency_checks.py 2010-07-09 09:50:35 UTC (rev 10479)
@@ -1,6 +1,7 @@
# $Id$
import checkpkg
+import os.path
import re
DEPRECATED_LIBRARY_LOCATIONS = (
@@ -17,7 +18,7 @@
r'^opt/csw/lib/python/site-packages.*',
)
-def Libraries(pkg_data, error_mgr, logger, path_and_pkg_by_basename):
+def Libraries(pkg_data, error_mgr, logger, messenger, path_and_pkg_by_basename):
pkgname = pkg_data["basic_stats"]["pkgname"]
logger.debug("Libraries(): pkgname = %s", repr(pkgname))
orphan_sonames = []
@@ -25,6 +26,7 @@
isalist = pkg_data["isalist"]
ldd_emulator = checkpkg.LddEmulator()
for binary_info in pkg_data["binaries_dump_info"]:
+ binary_path, binary_basename = os.path.split(binary_info["path"])
for soname in binary_info["needed sonames"]:
resolved = False
path_list = path_and_pkg_by_basename[soname].keys()
@@ -35,11 +37,18 @@
path_list)
runpath_tuple = (tuple(binary_info["runpath"])
+ tuple(checkpkg.SYS_DEFAULT_RUNPATH))
+ runpath_history = []
for runpath in runpath_tuple:
- resolved_path = ldd_emulator.ResolveSoname(runpath,
+ runpath = ldd_emulator.SanitizeRunpath(runpath)
+ runpath_list = ldd_emulator.ExpandRunpath(runpath, isalist, binary_path)
+ runpath_list = ldd_emulator.Emulate64BitSymlinks(runpath_list)
+ # To accumulate all the runpaths that we were looking at
+ runpath_history += runpath_list
+ resolved_path = ldd_emulator.ResolveSoname(runpath_list,
soname,
isalist,
- path_list)
+ path_list,
+ binary_path)
if resolved_path:
logger.debug("%s needed by %s:",
soname, binary_info["path"])
@@ -61,6 +70,10 @@
break
if not resolved:
orphan_sonames.append((soname, binary_info["path"]))
+ messenger.Message(
+ "%s could not be resolved for %s, with rpath %s, expanded to %s, "
+ "while the file was available at the following paths: %s"
+ % (soname, binary_info["path"], runpath_tuple, runpath_history, path_list))
orphan_sonames = set(orphan_sonames)
for soname, binary_path in orphan_sonames:
error_mgr.ReportError(
@@ -69,7 +82,7 @@
# TODO: Report orphan sonames here
return required_deps
-def ByFilename(pkg_data, error_mgr, logger, path_and_pkg_by_basename):
+def ByFilename(pkg_data, error_mgr, logger, messenger, path_and_pkg_by_basename):
pkgname = pkg_data["basic_stats"]["pkgname"]
req_pkgs_reasons = []
dep_regexes = [(re.compile(x), x, y)
Modified: csw/mgar/gar/v2/lib/python/package_checks.py
===================================================================
--- csw/mgar/gar/v2/lib/python/package_checks.py 2010-07-09 01:27:36 UTC (rev 10478)
+++ csw/mgar/gar/v2/lib/python/package_checks.py 2010-07-09 09:50:35 UTC (rev 10479)
@@ -298,14 +298,18 @@
# Resolving sonames for each binary
for pkg_data in pkgs_data:
pkgname = pkg_data["basic_stats"]["pkgname"]
- check_args = (pkg_data, error_mgr, logger, path_and_pkg_by_basename)
+ check_args = (pkg_data, error_mgr, logger, messenger,
+ path_and_pkg_by_basename)
req_pkgs_reasons = depchecks.Libraries(*check_args)
req_pkgs_reasons.extend(depchecks.ByFilename(*check_args))
missing_reasons_by_pkg = {}
for pkg, reason in req_pkgs_reasons:
if pkg not in missing_reasons_by_pkg:
- missing_reasons_by_pkg[pkg] = set()
- missing_reasons_by_pkg[pkg].add(reason)
+ missing_reasons_by_pkg[pkg] = list()
+ if len(missing_reasons_by_pkg[pkg]) < 4:
+ missing_reasons_by_pkg[pkg].append(reason)
+ elif len(missing_reasons_by_pkg[pkg]) == 4:
+ missing_reasons_by_pkg[pkg].append("...and more.")
declared_deps = pkg_data["depends"]
declared_deps_set = set([x[0] for x in declared_deps])
req_pkgs_set = set([x[0] for x in req_pkgs_reasons])
@@ -876,7 +880,8 @@
metadata["path"],
metadata["machine_id"],
cpu_type))
- messenger.Message(
+ messenger.OneTimeMessage(
+ "binary-placement",
"Files compiled for specific architectures must be placed in "
"subdirectories that match the architecture. "
"For example, a sparcv8+ binary must not be placed under "
Modified: csw/mgar/gar/v2/lib/python/package_checks_test.py
===================================================================
--- csw/mgar/gar/v2/lib/python/package_checks_test.py 2010-07-09 01:27:36 UTC (rev 10478)
+++ csw/mgar/gar/v2/lib/python/package_checks_test.py 2010-07-09 09:50:35 UTC (rev 10479)
@@ -339,7 +339,8 @@
binaries_dump_info[0]["runpath"] = tuple(testdata.rpaths.all_rpaths)
self.pkg_data["binaries_dump_info"] = binaries_dump_info[0:1]
BAD_PATHS = [
- '$ORIGIN/..',
+ # Whether this is a valid rpath, is debatable.
+ # '$ORIGIN/..',
'$ORIGIN/../../../usr/lib/v9',
'$ORIGIN/../../usr/lib',
'$ORIGIN/../lib',
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