Browse Source

Merge branch 'master' of git://git.debian.org/git/dpkg/dpkg into sourcev3

Conflicts:

	man/dpkg-source.1
	scripts/Makefile.am

(manually resolved)
Joey Hess 19 years ago
parent
commit
cbfe27aa54
47 changed files with 10890 additions and 747 deletions
  1. 46 0
      ChangeLog
  2. 1 1
      configure.ac
  3. 60 0
      debian/changelog
  4. 10 0
      debian/dpkg-dev.install
  5. 1 0
      debian/rules
  6. 26 0
      man/ChangeLog
  7. 2 0
      man/Makefile.am
  8. 52 0
      man/deb-symbols.5
  9. 12 4
      man/dpkg-buildpackage.1
  10. 164 0
      man/dpkg-gensymbols.1
  11. 120 22
      man/dpkg-shlibdeps.1
  12. 27 13
      man/dpkg-source.1
  13. 60 66
      man/po/de.po
  14. 522 127
      man/po/pl.po
  15. 4 0
      po/ChangeLog
  16. 55 89
      po/pl.po
  17. 50 0
      scripts/Dpkg/ErrorHandling.pm
  18. 82 0
      scripts/Dpkg/Path.pm
  19. 92 0
      scripts/Dpkg/Shlibs.pm
  20. 339 0
      scripts/Dpkg/Shlibs/Objdump.pm
  21. 326 0
      scripts/Dpkg/Shlibs/SymbolFile.pm
  22. 2 1
      scripts/Dpkg/Source/VCS/git.pm
  23. 205 0
      scripts/Dpkg/Version.pm
  24. 38 2
      scripts/Makefile.am
  25. 8 4
      scripts/dpkg-buildpackage.pl
  26. 234 0
      scripts/dpkg-gensymbols.pl
  27. 391 358
      scripts/dpkg-shlibdeps.pl
  28. 110 59
      scripts/dpkg-source.pl
  29. 4 0
      scripts/po/ChangeLog
  30. 3 0
      scripts/po/LINGUAS
  31. 6 1
      scripts/po/POTFILES.in
  32. 2593 0
      scripts/po/pl.po
  33. 11 0
      scripts/t/000_pod.t
  34. 80 0
      scripts/t/100_Dpkg_Version.t
  35. 148 0
      scripts/t/200_Dpkg_Shlibs.t
  36. 9 0
      scripts/t/200_Dpkg_Shlibs/ld.so.conf
  37. 1 0
      scripts/t/200_Dpkg_Shlibs/ld.so.conf.d/inf_recurse.conf
  38. 1 0
      scripts/t/200_Dpkg_Shlibs/ld.so.conf.d/normal.conf
  39. 1 0
      scripts/t/200_Dpkg_Shlibs/ld.so.conf.d/recursive.conf
  40. 1 0
      scripts/t/200_Dpkg_Shlibs/ld.so.conf_2
  41. 350 0
      scripts/t/200_Dpkg_Shlibs/objdump.glib-ia64
  42. 2276 0
      scripts/t/200_Dpkg_Shlibs/objdump.libc6-2.3
  43. 2345 0
      scripts/t/200_Dpkg_Shlibs/objdump.libc6-2.6
  44. 4 0
      scripts/t/200_Dpkg_Shlibs/symbols.fake-1
  45. 8 0
      scripts/t/200_Dpkg_Shlibs/symbols.fake-2
  46. 7 0
      scripts/t/200_Dpkg_Shlibs/symbols.include-1
  47. 3 0
      scripts/t/200_Dpkg_Shlibs/symbols.include-2

+ 46 - 0
ChangeLog

@@ -1,3 +1,49 @@
+2007-10-09  Guillem Jover  <guillem@debian.org>
+
+	* scripts/dpkg-gensymbols.pl: Use new Dpkg module. Do not declare
+	nor initialize $version, $dpkglibdir and $progname anymore.
+
+2007-10-09  Frank Lichtenheld  <djpig@debian.org>
+
+	* scripts/dpkg-source.pl (usage): -W is the default
+	for quite some time already. Adapt the description of
+	-W and -E.
+	* scripts/dpkg-buildpackage.pl (usage): likewise.
+
+	* scripts/dpkg-buildpackage.pl: Add -z/-Z to
+	passthrough opts (will be passed to dpkg-source).
+
+	* scripts/dpkg-source.pl: Support a subset of
+	wig&pen (aka Format: 2.0) on build:
+	Use .orig.tar.(bz2|lzma) if they are available
+	and no .gz can be found. Also let the user specify
+	via -Z(gzip|bzip2|lzma) how files that need to be
+	generated should be compressed. -z([1-9]|best|fast)
+	can be used to specify the compression level
+	to use.
+
+2007-10-08  Raphael Hertzog  <hertzog@debian.org>
+	    Frank Lichtenheld  <djpig@debian.org>
+
+	* Merge dpkg-shlibdeps-buxy branch.
+
+	* scripts/dpkg-shlibdeps.pl: heavily reworked to support "symbols"
+	files. Lots of the code has been modularized in perl modules
+	Dpkg::Shlibs::*.
+
+	* scripts/dpkg-gensymbols.pl: new script used to generated symbols
+	files at package build time. It shall be used by packages of libraries.
+
+	* man/dpkg-{shlibdeps,gensymbols}.1: updated and created manual
+	pages documenting the changes above.
+
+	* scripts/t/*: Added some non-regression test on many parts of the
+	newly introduced perl modules.
+
+2007-10-08  Guillem Jover  <guillem@debian.org>
+
+	* configure.ac: Bump version to 1.14.8~.
+
 2007-10-08  Guillem Jover  <guillem@debian.org>
 
 	* configure.ac: Release 1.14.7.

+ 1 - 1
configure.ac

@@ -1,7 +1,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.59)
-AC_INIT([dpkg], [1.14.7], [debian-dpkg@lists.debian.org])
+AC_INIT([dpkg], [1.14.8~], [debian-dpkg@lists.debian.org])
 AC_CONFIG_SRCDIR([lib/dpkg.h])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_AUX_DIR([config])

+ 60 - 0
debian/changelog

@@ -1,3 +1,63 @@
+dpkg (1.14.8) UNRELEASED; urgency=low
+
+  [ Raphael Hertzog ]
+  * Merge dpkg-shlibdeps-buxy branch, dpkg-shlibdeps has been heavily
+    reworked:
+    * it supports "symbols" files to generate finer-grained
+      dependencies. Closes: #430367
+      Those files can be created by the new dpkg-gensymbols
+      command.
+    * it uses now all paths in RPATH (instead of only the first).
+      Closes: #395942
+    * it's now able to parse include directives in /etc/ld.so.conf.
+      Closes: #431597
+    * libraries are also searched in the public directories of packages
+      being built and thus debian/shlibs.local can effectively define
+      dependencies for libraries that are being built. Closes: #80340
+    * "symbols" files use the full SONAME as key instead of splitting it in
+      (name, version) like the "shlibs" format requires it. This allows
+      binaries to be linked with unversioned libraries and not fail.
+      Closes: #48208
+      Note that unversioned libraries are still a very bad idea.
+    * dpkg-shlibdeps now supports "-x<package>" options that can be used
+      to exclude packages from generated dependencies. This is
+      particalularly useful to avoid dependencies on ourselves when a
+      package contains a binary and a library (without requiring an
+      shlibs.local file to override the usual shlibs file). It might also
+      be used to avoid other unwanted dependencies (use with care though).
+      Closes: #41907, #109954
+    * If dpkg-shlibdeps doesn't find any dependency information for a
+      shared library that is actively used, then it will fail. This can be
+      disabled with the option --ignore-missing-info. Closes: #10807
+
+  [ Frank Lichtenheld ]
+  * Add $(MAKE) check to build target
+  * Allow to use other compressions than gzip on dpkg-source -b
+    (NOTE: this will result in a Format: 2.0 source package!).
+    Closes: #382673
+
+  [ Updated dpkg translations ]
+  * Polish (Robert Luberda).
+
+  [ Updated man pages translations ]
+  * Polish (Robert Luberda).
+
+  [ Updated scripts translations ]
+  * Polish (Robert Luberda).
+
+ -- Raphael Hertzog <hertzog@debian.org>  Mon, 08 Oct 2007 20:49:51 +0200
+
+dpkg (1.14.8~newshlib) experimental; urgency=low
+
+  [ Raphael Hertzog ]
+  * Snapshot of upcoming dpkg 1.14.8 with improved dpkg-shlibdeps
+    supporting symbols files.
+
+  [ Updated man pages translations ]
+  * German (Helge Kreutzmann).
+
+ -- Raphael Hertzog <hertzog@debian.org>  Mon, 08 Oct 2007 20:22:57 +0200
+
 dpkg (1.14.7) unstable; urgency=low
 
   [ Guillem Jover ]

+ 10 - 0
debian/dpkg-dev.install

@@ -8,6 +8,7 @@ usr/bin/dpkg-checkbuilddeps
 usr/bin/dpkg-distaddfile
 usr/bin/dpkg-genchanges
 usr/bin/dpkg-gencontrol
+usr/bin/dpkg-gensymbols
 usr/bin/dpkg-name
 usr/bin/dpkg-parsechangelog
 usr/bin/dpkg-scanpackages
@@ -16,6 +17,11 @@ usr/bin/dpkg-shlibdeps
 usr/bin/dpkg-source
 usr/lib/dpkg/controllib.pl
 usr/lib/dpkg/parsechangelog
+usr/share/perl5/Dpkg/Path.pm
+usr/share/perl5/Dpkg/Version.pm
+usr/share/perl5/Dpkg/ErrorHandling.pm
+usr/share/perl5/Dpkg/Shlibs.pm
+usr/share/perl5/Dpkg/Shlibs
 usr/share/locale/*/LC_MESSAGES/dpkg-dev.mo
 usr/share/man/*/*/822-date.1
 usr/share/man/*/822-date.1
@@ -27,6 +33,8 @@ usr/share/man/*/*/deb-override.5
 usr/share/man/*/deb-override.5
 usr/share/man/*/*/deb-shlibs.5
 usr/share/man/*/deb-shlibs.5
+usr/share/man/*/*/deb-symbols.5
+usr/share/man/*/deb-symbols.5
 usr/share/man/*/*/deb-old.5
 usr/share/man/*/deb-old.5
 usr/share/man/*/*/deb.5
@@ -43,6 +51,8 @@ usr/share/man/*/*/dpkg-genchanges.1
 usr/share/man/*/dpkg-genchanges.1
 usr/share/man/*/*/dpkg-gencontrol.1
 usr/share/man/*/dpkg-gencontrol.1
+usr/share/man/*/*/dpkg-gensymbols.1
+usr/share/man/*/dpkg-gensymbols.1
 usr/share/man/*/*/dpkg-name.1
 usr/share/man/*/dpkg-name.1
 usr/share/man/*/*/dpkg-parsechangelog.1

+ 1 - 0
debian/rules

@@ -59,6 +59,7 @@ build: build-tree/config.status
 	dh_testdir
 
 	cd build-tree && $(MAKE)
+	cd build-tree && $(MAKE) check
 
 # Install the package underneath debian/tmp
 install: build

+ 26 - 0
man/ChangeLog

@@ -1,3 +1,29 @@
+2007-10-09  Frank Lichtenheld  <djpig@debian.org>
+
+	* dpkg-source.1: -W is the default for quite
+	some time already. Adapt the description of
+	-W and -E.
+	* dpkg-buildpackage.1: likewise.
+
+	* dpkg-source.1: Change the rest of the
+	man page to not contain any hardcoded
+	.gz references.
+
+	* dpkg-buildpackage.1: Document all
+	options only passed to dpkg-source.
+	-s[nsAkurKUR], -z, and -Z were missing.
+
+	* dpkg-source.1: Document -Z and -z.
+
+2007-10-08  Robert Luberda  <robert@debian.org>
+
+	* po/pl.po: Update to 1183t19f101u.
+
+2007-10-08  Helge Kreutzmann  <debian@helgefjell.de>
+
+	* po/de.po: Updated to 1249t0f54u.
+	* Removed the FIXMEs left in de.po by accident
+
 2007-10-08  Guillem Jover  <guillem@debian.org>
 
 	* po/dpkg-man.pot: Regenerated.

+ 2 - 0
man/Makefile.am

@@ -53,6 +53,7 @@ dist_man_MANS = \
 	deb-control.5 \
 	deb-shlibs.5 \
 	deb-substvars.5 \
+	deb-symbols.5 \
 	deb-old.5 \
 	deb-override.5 \
 	deb.5 \
@@ -64,6 +65,7 @@ dist_man_MANS = \
 	dpkg-divert.8 \
 	dpkg-genchanges.1 \
 	dpkg-gencontrol.1 \
+	dpkg-gensymbols.1 \
 	dpkg-name.1 \
 	dpkg-parsechangelog.1 \
 	dpkg-query.1 \

+ 52 - 0
man/deb-symbols.5

@@ -0,0 +1,52 @@
+.\" Author: Raphael Hertzog
+.TH deb\-symbols 5 "2007-07-16" "Debian Project" "dpkg utilities"
+.SH NAME
+deb\-symbols \- Debian's extended shared library information file
+.
+.SH SYNOPSIS
+symbols
+.
+.SH DESCRIPTION
+The format for an extended shared library dependency information entry
+in these files is:
+.PP
+<library soname> <main dependency template>
+.br
+[ | <alternative dependency template> ]
+.br
+[ ... ]
+ <symbol> <mininal version>[ <id of dependency template> ]
+.P
+The \fIlibrary soname\fR is exactly the value of the SONAME field
+as exported by \fBobjdump\fR. A \fIdependency template\fR is a
+dependency where \fI#MINVER#\fR is dynamically replaced either by
+a version check like "(>= \fIminimal version\fR)" or by nothing (if
+an unversionned dependency is deemed sufficient). 
+.P
+Each exported \fIsymbol\fR (listed as \fIname\fR@\fIversion\fR, with
+\fIversion\fR being "Base" if the library is not versioned) is associated
+to a \fIminimal version\fR of its dependency template (the main dependency
+template is used if \fIid of dependency template\fR is not present). The
+first alternative dependency template is numbered 1, the second one 2,
+etc.
+.SH EXAMPLES
+.SS Simple symbols file
+.PP 
+libftp.so.3 libftp3 #MINVER#
+ DefaultNetbuf@Base 3.1-1-6
+ FtpAccess@Base 3.1-1-6
+ [...]
+.SS Advanced symbols file
+.PP 
+libGL.so.1 libgl1
+.br
+| libgl1-mesa-glx #MINVER#
+ publicGlSymbol@Base 6.3-1
+ [...]
+ implementationSpecificSymbol@Base 6.5.2-7 1
+ [...]
+.SH SEE ALSO
+.BR http://wiki.debian.org/Projects/ImprovedDpkgShlibdeps
+.br
+.BR dpkg\-shlibdeps (1),
+.BR dpkg\-gensymbols (1).

+ 12 - 4
man/dpkg-buildpackage.1

@@ -85,15 +85,15 @@ Check build dependencies and conflicts; abort if unsatisfied.
 .B \-d
 Do not check build dependencies and conflicts.
 .TP
-.B \-W
-Turn certain errors into warnings. Only \fBdpkg\-source\fP uses this, but
+.B \-E
+Turn certain warnings into errors. Only \fBdpkg\-source\fP uses this, but
 .BR dpkg\-buildpackage
 recognizes it, and passes it thru to
 .BR dpkg\-source "."
 .TP
-.B \-E
+.B \-W
 Negates a previously set
-.BR \-W "."
+.BR \-E "."
 Only \fBdpkg\-source\fP uses this, but
 .BR dpkg\-buildpackage
 recognizes it, and passes it thru to
@@ -178,6 +178,14 @@ Passed unchanged to
 .BR dpkg\-source .
 May be repeated multiple times.
 .TP
+.BR \-s [ nsAkurKUR ]
+Passed unchanged to
+.BR dpkg\-source .
+.TP
+.BR \-z ", " \-Z
+Passed unchanged to
+.BR dpkg\-source .
+.TP
 .BI \-\-admindir= dir
 Change the location of the \fBdpkg\fR database. The default location is
 \fI/var/lib/dpkg\fP.

+ 164 - 0
man/dpkg-gensymbols.1

@@ -0,0 +1,164 @@
+.\" Author: Raphael Hertzog
+.TH dpkg\-gensymbols 1 "2007-07-16" "Debian Project" "dpkg utilities"
+.SH NAME
+dpkg\-gensymbols \- generate symbols files (shared library dependency information)
+.
+.SH SYNOPSIS
+.B dpkg\-gensymbols
+.RI [ options ]
+.
+.SH DESCRIPTION
+.B dpkg\-gensymbols
+scans a temporary build tree (debian/tmp by default) looking for libraries
+and generate a \fIsymbols\fR file describing them. This file, if
+non-empty, is then installed in the DEBIAN subdirectory of the build tree
+so that it ends up included in the control information of the package.
+.P
+When generating those files, it uses as input some symbols files
+provided by the maintainer. It looks for the following files (and use the
+first that is found):
+.IP \(bu 4
+debian/\fIpackage\fR.symbols.\fIarch\fR
+.IP \(bu 4
+debian/symbols.\fIarch\fR
+.IP \(bu 4
+debian/\fIpackage\fR.symbols
+.IP \(bu 4
+debian/symbols
+.P
+The main interest of those files is to provide the minimal version
+associated to each symbol provided by the libraries. Usually it
+corresponds to the first version of that package that provided the symbol,
+but it can be manually incremented by the maintainer if the ABI of the
+symbol is extended without breaking backwards compatibility. It's the
+responsibility of the maintainer to keep those files up-to-date and
+accurate, but \fBdpkg\-gensymbols\fR helps him.
+.P
+When the generated symbols files differ from the maintainer supplied
+one, \fBdpkg\-gensymbols\fR will print a diff between the two versions.
+Furthermore if the difference are too significant, it will even fail (you
+can customize how much difference you can tolerate, see the \fB\-c\fR
+option).
+.SH MAINTAINING SYMBOLS FILES
+The symbols files are really useful only if they reflect the evolution of
+the package through several releases. Thus the maintainer has to update
+them every time that a new symbol is added so that its associated minimal
+version matches reality. To do this properly he can use the diffs contained
+in the build logs. In most cases, the diff can be directly applied to his
+debian/\fIpackage\fR.symbols file.
+.P
+Before applying any patch to the symbols file, the maintainer should
+double-check that it's sane. Public symbols are not supposed to disappear,
+so the patch should ideally only add new lines.
+.SS Using includes
+.P 
+When the set of exported symbols differ between architectures, it's no
+more possible to use a common symbols file. Using one file per
+architecture works, but it can also lead to duplication of information.
+In those cases, you can factorize the common part in some external file
+and include that file in your \fIpackage\fR.symbols.\fIarch\fR file by
+using an include directive like this:
+.PP
+#include "\fIpackages\fR.symbols.common"
+.P
+The symbols files are read line by line, and include directives
+are processed as soon as they are encountered. This means that
+the content of the included file can override any content that appeared
+before the include directive and that any content after the
+directive can override anything contained in the included file.
+.P
+An included file must be a valid symbols file on its own. Thus you have
+to repeat the header line containing the SONAME of the library and the
+dependency template. Remember that those lines might override the header
+defined previously in the main symbols file. Thus the recommended way to
+handle architecture specific information is to put include directives
+directly at the beginning of the symbols file:
+.PP
+#include "libsomething1.symbols.common"
+.br
+libsomething.so.1 libsomething1 #MINVER#
+ arch_specific_symbol@Base 1.0
+.SS Good library management
+.P
+A well-maintained library has the following features:
+.IP \(bu 4
+its API is stable (public symbols are never dropped, only new public
+symbols are added) and changes in incompatible ways only when the SONAME
+changes;
+.IP \(bu 4
+ideally, it uses symbol versioning to achieve ABI stability despite
+internal changes and API extension;
+.IP \(bu 4
+it doesn't export private symbols.
+.P
+While maintaining the symbols file, it's easy to notice appearance and
+disappearance of symbols. But it's more difficult to catch incompatible
+API and ABI change. Thus the maintainer should read thoroughly the
+upstream changelog looking for cases where the rules of good library
+management have been broken. If potential problems are discovered,
+the upstream author should be notified as an upstream fix is always better
+than a Debian specific work-around.
+.SH OPTIONS
+.TP
+.BI \-P package-build-dir
+Scan \fIpackage-build-dir\fR instead of debian/tmp.
+.TP
+.BI \-p package
+Define the package name. Required if more than one binary package is listed in
+debian/control (or if there's no debian/control file).
+.TP
+.BI \-v version
+Define the package version. Defaults to the version extracted from
+debian/changelog. Required if called outside of a source package tree.
+.TP
+.BI \-e library-file
+Only analyze libraries explicitely listed instead of finding all public
+libraries. You can use a regular expression in \fIlibrary-file\fR to match
+multiple libraries with a single argument (otherwise you need multiple
+\fB\-e\fR).
+.TP
+.B \-O
+Print the generated symbols file to standard output, rather than being
+stored in the package build tree.
+.TP 
+.BI \-O filename
+Store the generated symbols file as \fIfilename\fR. If \fIfilename\fR is
+pre-existing, its content is used as basis for the generated symbols file.
+You can use this feature to update a symbols file so that it matches a
+newer upstream version of your library.
+.TP
+.BI \-c [0-4]
+Define the checks to do when comparing the generated symbols file
+with the file used as starting point. By default the level is 1.
+Increasing levels do more checks and include all checks of lower levels.
+Level 0 disables all checks. Level 1 fails if some symbols have
+disappeared. Level 2 fails if some new symbols have been introduced.
+Level 3 fails if some libraries have disappeared. Level 4 fails if some
+libraries have been introduced.
+.TP
+.BI \-d
+Enable debug mode. Numerous messages are displayed to explain what 
+.B dpkg\-gensymbols
+does.
+.TP
+.BR \-h ", " \-\-help
+Show the usage message and exit.
+.TP
+.BR \-\-version
+Show the version and exit.
+.
+.SH "SEE ALSO"
+.BR http://people.redhat.com/drepper/symbol-versioning
+.br
+.BR http://people.redhat.com/drepper/goodpractice.pdf
+.br
+.BR http://people.redhat.com/drepper/dsohowto.pdf
+.br
+.BR deb\-symbols (5),
+.BR dpkg\-shlibdeps (1).
+.
+.SH AUTHORS
+Copyright (C) 2007 Rapha\[:e]l Hertzog
+.sp
+This is free software; see the GNU General Public Licence version 2 or later
+for copying conditions. There is NO WARRANTY.

+ 120 - 22
man/dpkg-shlibdeps.1

@@ -1,4 +1,4 @@
-.TH dpkg\-shlibdeps 1 "2007-06-12" "Debian Project" "dpkg utilities"
+.TH dpkg\-shlibdeps 1 "2007-07-16" "Debian Project" "dpkg utilities"
 .SH NAME
 dpkg\-shlibdeps \- generate shared library substvar dependencies
 .
@@ -21,18 +21,76 @@ where
 is a dependency field name. Any other variables starting
 .I shlibs:
 are removed from the file.
+.P
 .B dpkg\-shlibdeps
-will read shared library dependency information from
-.BR debian/shlibs.local ,
-.BR /etc/dpkg/shlibs.override ,
-the
-.B shlibs
-control area file of the package containing the file which
-.B objdump
-reports as satisfying the library dependency, or
-.BR /etc/dpkg/shlibs.default .
-The first match will be used.
-.
+has two possible sources of information to generate dependency
+information. Either
+.I symbols
+files or
+.I shlibs
+files. For each binary that
+.B dpkg\-shlibdeps
+analyzes, it finds out the list of libraries that it's linked with.
+Then, for each library, it looks up either the 
+.I symbols
+file, or the
+.I shlibs
+file (if the former doesn't exist). Both files are supposed to be provided
+by the library package and should thus be available as
+/var/lib/dpkg/info/\fIpackage\fR.\fIsymbols\fR
+or /var/lib/dpkg/info/\fIpackage\fR.\fIshlibs\fR. The package name is
+identified in two steps: find the library file on the system (looking in
+the same directories that \fBld.so\fR would use), then use
+.BI "dpkg -S " library\-file
+to lookup the package providing the library.
+.SS Symbols files
+Symbols files contain finer-grained dependency information by providing
+the minimum dependency for each symbol that the library exports. The
+script tries to find a symbols file associated to a library package
+in the following places (first match is used):
+.IP debian/*/DEBIAN/symbols
+Shared library information generated by the current build process that also invoked
+.BR dpkg\-shlibdeps .
+They are generated by 
+.BR dpkg\-gensymbols (1).
+.IP /etc/dpkg/symbols/\fIpackage\fR.symbols.\fIarch\fR
+.IP /etc/dpkg/symbols/\fIpackage\fR.symbols
+Per-system overriding shared library dependency information.
+\fIarch\fR is the architecture of the current system (obtained by
+.BR "dpkg-architecture -qDEB_HOST_ARCH" ).
+.IP \fIadmindir\fR/info/\fIpackage\fR.symbols
+Package-provided shared library dependency information.
+Unless overriden, \fIadmindir\fR is /var/lib/dpkg.
+.P 
+While scanning the symbols used by all binaries,
+.B dpkg\-shlibdeps
+remembers the (biggest) minimal version needed for each library. At the end
+of the process, it is able to write out the minimal dependency for every
+library used (provided that the information of the \fIsymbols\fR files are
+accurate).
+.SS Shlibs files
+Shlibs files associate directly a library to a dependency (without looking
+at the symbols). It's thus often stronger than really needed but very safe
+and easy to handle.
+.P
+The dependencies for a library are looked up in several places. The first
+file providing informations for the library of interest is used:  
+.IP debian/shlibs.local
+Package-local overriding shared library dependency information.
+.IP /etc/dpkg/shlibs.override
+Per-system overriding shared library dependency information.
+.IP debian/*/DEBIAN/shlibs
+Shared library information generated by the current build process that also invoked
+.BR dpkg\-shlibdeps .
+.IP \fIadmindir\fR/info/\fIpackage\fR.shlibs
+Package-provided shared library dependency information.
+Unless overriden, \fIadmindir\fR is /var/lib/dpkg.
+.IP /etc/dpkg/shlibs.default
+Per-system default shared library dependency information.
+.P
+The extracted dependencies are then directly used (except if they are
+filtered out because they have been identified as duplicate, or as weaker
+than another dependency).
 .SH OPTIONS
 .B dpkg\-shlibdeps
 interprets non-option arguments as executable names, just as if they'd
@@ -103,6 +161,24 @@ Write substitution variables in
 the default is
 .BR debian/substvars .
 .TP
+.BI \-v
+Enable verbose mode. Numerous messages are displayed to explain what 
+.B dpkg\-shlibdeps
+does.
+.TP
+.BI \-x package
+Exclude the package from the generated dependencies. This is useful to
+avoid self-dependencies for packages which provide ELF binaries
+(executables or library plugins) using a library contained in the same
+package. This option can be used multiple times to exclude several
+packages.
+.TP
+.BI \-\-ignore\-missing\-info
+Do not fail if dependency information can't be found for a shared library.
+Usage of this option is discouraged, all libraries should provide
+dependency information (either with shlibs files, or with symbols files)
+even if they are not yet used by other packages.  
+.TP
 .BI \-\-admindir= dir
 Change the location of the \fBdpkg\fR database. The default location is
 \fI/var/lib/dpkg\fP.
@@ -113,24 +189,46 @@ Show the usage message and exit.
 .BR \-\-version
 Show the version and exit.
 .
-.SH FILES
-.TP
-.B debian/shlibs.local
-Package-local overriding shared library dependency information.
+.SH WARNINGS
+Since
+.B dpkg\-shlibdeps
+analyzes the set of symbols used by each binary of the generated package,
+it is able to emit warnings in several cases. They inform you of things
+that can be improved in the package. In most cases, those improvements
+concern the upstream sources directly. By order of decreasing importance,
+here are the various warnings that you can encounter:
 .TP
-.B /etc/dpkg/shlibs.override
-Per-system overriding shared library dependency information.
+.BI symbol " sym" " used by " binary " found in none of the libraries."
+The indicated symbol has not been found in the libraries linked with the
+binary. The \fIbinary\fR is most likely a library and it needs to be linked
+with an additional library during the build process (option \fB-l\fR\fIlibrary\fR
+of the linker).
 .TP
-.B /etc/dpkg/shlibs.default
-Per-system default shared library dependency information.
-.
+.IB binary " shouldn't be linked with " library " (it uses none of its symbols)."
+The \fIbinary\fR is linked to a library that it doesn't need. It's not a
+problem but some small performance improvements in binary load time
+can be obtained by not linking this library to this binary. 
+
+Furthermore, in some cases, this will lead to a non-versionned dependency
+on the library that could have been avoided if the binary was only linked
+against the library that it really uses. The exception to this rule is
+when several binaries are linked against the same set of libraries but
+each binary only uses a subset of those. You will have warnings on
+individual binaries, but the set of libraries needed at the package level
+is the same whether you fix the binaries or not.
 .SH "SEE ALSO"
-.BR deb\-shlibs (5).
+.BR deb\-shlibs (5),
+.BR deb\-symbols (5),
+.BR dpkg-gensymbols (1).
 .
 .SH AUTHORS
 Copyright (C) 1995-1996 Ian Jackson
 .br
 Copyright (C) 2000 Wichert Akkerman
+.br
+Copyright (C) 2006 Frank Lichtenheld
+.br
+Copyright (C) 2007 Rapha\[:e]l Hertzog
 .sp
 This is free software; see the GNU General Public Licence version 2 or later
 for copying conditions. There is NO WARRANTY.

+ 27 - 13
man/dpkg-source.1

@@ -51,7 +51,9 @@ the empty string if the package is a Debian-specific one and so has no
 Debianisation diffs. If no second argument is supplied then
 .B dpkg\-source
 will look for the original source tarfile
-.IB package _ upstream-version .orig.tar.gz
+.IB package _ upstream-version .orig.tar. extension
+(where \fIextension\fP is one of
+.BR gz ", " bz2 ", and " lzma )
 or the original source directory
 .IB directory .orig
 depending on the \fB\-sX\fP arguments.
@@ -103,27 +105,39 @@ Override or add an output control file field.
 .BI \-U field
 Remove an output control file field.
 .TP
-.BI \-W
-This option turns certain errors into warnings.
-.TP
 .BI \-E
+This option turns certain warnings into errors.
+.TP
+.BI \-W
 This option negates a previously set
-.BR \-W "."
+.BR \-E "."
+.TP
+.BR \-Z \fIcompression\fP
+Specify the compression to use for created files (tarballs and diffs).
+Note that this option will not cause existing tarballs to be recompressed,
+it only affects new files. Supported values are:
+.IR gzip ", " bzip2 ", and " lzma .
+\fIgzip\fP is the default.
+.TP
+.BR \-z \fIlevel\fP
+Compression level to use. As with \fB\-Z\fP it only affects newly created
+files. Supported values are:
+.IR 1 " to " 9 ", " best ", and " fast .
+\fI9\fP is the default.
 .TP
 .BR \-i [\fIregexp\fP]
 You may specify a perl regular expression to match files you want
 filtered out of the list of files for the diff. (This list is
 generated by a find command.) (If the source package is being built as a
 version 3 source package using a VCS, this is instead used to
-ignore uncommitted files.) \fB\-i\fR by itself enables the option,
+ignore uncommitted files.) \fB\-i\fP by itself enables the option,
 with a default that will filter out control files and directories of the
 most common revision control systems, backup and swap files and Libtool
 build output directories. There can only be one active regexp, of multiple
-\-i options only the last one will take effect.
-
+\fB\-i\fP options only the last one will take effect.
 
 This is very helpful in cutting out extraneous files that get included
-in the .diff.gz, e.g. if you maintain your source in a revision control
+in the diff, e.g. if you maintain your source in a revision control
 system and want to use a checkout to build a source package without
 including the additional files and directories that it will usually
 contain (e.g. CVS/, .cvsignore, .svn/). The default regexp is already
@@ -136,12 +150,12 @@ the neccessary anchors (e.g. '(^|/)', '($|/)') yourself.
 If this option is specified, the pattern will be passed to
 .BR tar (1)'s
 \-\-exclude
-option when it is called to generate a .orig.tar.gz or .tar.gz file. For
+option when it is called to generate a .orig.tar or .tar file. For
 example, \-ICVS will make tar skip over CVS directories when generating
 a .tar.gz file. The option may be repeated multiple times to list multiple
 patterns to exclude.
 
-\fB\-I\fR by itself adds default \-\-exclude options that will
+\fB\-I\fP by itself adds default \-\-exclude options that will
 filter out control files and directories of the most common revision
 control systems, backup and swap files and Libtool build output
 directories.
@@ -174,7 +188,7 @@ a VCS, these options do not make sense, and will be ignored.
 .TP
 .BR \-sk
 Specifies to expect the original source as a tarfile, by default
-.IB package _ upstream-version .orig.tar.gz\fR.
+.IB package _ upstream-version .orig.tar. extension \fR.
 It will leave this original source in place as a tarfile, or copy it
 to the current directory if it isn't already there.
 .TP
@@ -198,7 +212,7 @@ but will remove that directory after it has been used.
 .TP
 .B \-ss
 Specifies that the original source is available both as a directory
-and as a tarfile. If will use the directory to create the diff, but
+and as a tarfile. dpkg-source will use the directory to create the diff, but
 the tarfile to create the
 .BR .dsc .
 This option must be used with care - if the directory and tarfile do

+ 60 - 66
man/po/de.po

@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: dpkg man pages\n"
 "POT-Creation-Date: 2007-10-08 07:26+0300\n"
-"PO-Revision-Date: 2007-10-07 16:38+0200\n"
+"PO-Revision-Date: 2007-10-08 18:45+0200\n"
 "Last-Translator: Helge Kreutzmann <debian@helgefjell.de>\n"
 "Language-Team: German <debian-l10n-german@lists.debian.org>\n"
 "MIME-Version: 1.0\n"
@@ -604,9 +604,9 @@ msgstr "deb-control"
 
 # type: TH
 #: ../../man/deb-control.5:3
-#, fuzzy, no-wrap
+#, no-wrap
 msgid "2007-10-08"
-msgstr "2007-03-08"
+msgstr "2007-10-08"
 
 # type: Plain text
 #: ../../man/deb-control.5:6
@@ -767,17 +767,15 @@ msgstr ""
 
 # type: Plain text
 #: ../../man/deb-control.5:71
-#, fuzzy
 msgid ""
 "In Debian, the B<Section> and B<Priority> fields have a defined set of "
 "accepted values based on the Policy Manual.  A list of these values can be "
 "obtained from the latest version of the B<debian-policy> package."
 msgstr ""
 "In Debian haben die B<Section>- und B<Priority>-Felder einen definierten "
-"Satz an akzeptierten Werten, basierend auf dem Richtlinien-Handbuch. Sie "
-"werden verwendet, um zu entscheiden, wie Pakete im Archiv angeordnet werden. "
-"Eine Liste dieser Werte kann aus der neusten Version des B<debian-policy>-"
-"Pakets erhalten werden."
+"Satz an akzeptierten Werten, basierend auf dem Richtlinien-Handbuch. Eine "
+"Liste dieser Werte kann aus der neusten Version des Pakets B<debian-policy> "
+"erhalten werden."
 
 # type: TP
 #: ../../man/deb-control.5:71
@@ -822,20 +820,20 @@ msgstr ""
 
 # type: TP
 #: ../../man/deb-control.5:86
-#, fuzzy, no-wrap
+#, no-wrap
 msgid "B<Origin:> E<lt>nameE<gt>"
-msgstr "B<Source:> E<lt>Quell-NameE<gt>"
+msgstr "B<Origin:> E<lt>NameE<gt>"
 
 # type: Plain text
 #: ../../man/deb-control.5:89
 msgid "The name of the distribution this package is originating from."
-msgstr ""
+msgstr "Der Name der Distribution, aus der dieses Paket ursprünglich stammt."
 
 # type: TP
 #: ../../man/deb-control.5:89
-#, fuzzy, no-wrap
+#, no-wrap
 msgid "B<Bugs:> E<lt>urlE<gt>"
-msgstr "B<Homepage:> E<lt>URLE<gt>"
+msgstr "B<Bugs:> E<lt>URLE<gt>"
 
 # type: Plain text
 #: ../../man/deb-control.5:93
@@ -844,6 +842,9 @@ msgid ""
 "is B<E<lt>bts_typeE<gt>://E<lt>bts_addressE<gt>>, like B<debbugs://bugs."
 "debian.org>."
 msgstr ""
+"Die URL der Fehlerdatenbank für dieses Paket. Das derzeit verwendete Format "
+"ist B<E<lt>BTS_ArtE<gt>://E<lt>BTS_AdresseE<gt>> wie in B<debbugs://bugs."
+"debian.org>."
 
 # type: TP
 #: ../../man/deb-control.5:93
@@ -4317,9 +4318,9 @@ msgstr "dpkg-buildpackage"
 
 # type: TH
 #: ../../man/dpkg-buildpackage.1:1
-#, fuzzy, no-wrap
+#, no-wrap
 msgid "2007-09-28"
-msgstr "2007-09-08"
+msgstr "2007-09-28"
 
 # type: Plain text
 #: ../../man/dpkg-buildpackage.1:4
@@ -4453,9 +4454,9 @@ msgstr ""
 
 # type: TP
 #: ../../man/dpkg-buildpackage.1:49
-#, fuzzy, no-wrap
+#, no-wrap
 msgid "B<-j>I<jobs>"
-msgstr "B<-L>I<libverzeichnis>"
+msgstr "B<-j>I<Aufträge>"
 
 # type: Plain text
 #: ../../man/dpkg-buildpackage.1:60
@@ -4623,7 +4624,6 @@ msgstr "B<-r>I<root-werde-Befehl>"
 # type: Plain text
 #.  what happens, if it contains spaces? (hs)
 #: ../../man/dpkg-buildpackage.1:137
-#, fuzzy
 msgid ""
 "When B<dpkg-buildpackage> needs to execute part of the build process as "
 "root, it prefixes the command it executes with I<gain-root-command> if one "
@@ -4639,12 +4639,13 @@ msgid ""
 msgstr ""
 "Wenn B<dpkg-buildpackage> einen Teil des Bauprozesses als Root ausführen "
 "muss, stellt es dem auszführenden Befehl den I<root-werde-Befehl> voran, "
-"falls dieser angegeben wurde. Der I<root-werde-Befehl> sollte der Name des "
-"Programmes im B<PATH> sein und wird als Argumente den Namen des wirklich "
+"falls dieser angegeben wurde. Andernfalls wird standardmäßig B<fakeroot> "
+"verwendet, falls es vorhanden ist. Der I<root-werde-Befehl> sollte der Name "
+"des Programmes im B<PATH> sein und wird als Argumente den Namen des wirklich "
 "auszuführenden Befehles und dessen Argumente erhalten. Der I<root-werde-"
 "Befehl> sollte keine Leerzeichen oder andere Shell-Metazeichen enthalten. "
 "Typischerweise ist der I<root-werde-Befehl> B<fakeroot>, B<sudo>, B<super> "
-"oder B<really>. B<su> ist nicht geeignet, da es die B<-c>-Option zur "
+"oder B<really>. B<su> ist nicht geeignet, da es eine B<-c>-Option zur "
 "Ausführung eines Befehles benötigt und selbst dann kann es nur die Shell des "
 "Benutzers mit B<-c> aufrufen, anstatt Argumente individuell zur Ausführung "
 "zu übergeben."
@@ -4719,9 +4720,9 @@ msgstr "Wird unver
 
 # type: TP
 #: ../../man/dpkg-buildpackage.1:175
-#, fuzzy, no-wrap
+#, no-wrap
 msgid "B<-I>I<[pattern]>"
-msgstr "B<--list>I< Glob-Muster>"
+msgstr "B<-I>I<[Muster]>"
 
 # type: Plain text
 #: ../../man/dpkg-buildpackage.1:180
@@ -4771,9 +4772,8 @@ msgstr ""
 
 # type: Plain text
 #: ../../man/dpkg-buildpackage.1:209
-#, fuzzy
 msgid "Copyright (C) 2007 Frank Lichtenheld"
-msgstr "Copyright (C) 2000 Wichert Akkerman"
+msgstr "Copyright (C) 2007 Frank Lichtenheld"
 
 # type: TH
 #: ../../man/dpkg-checkbuilddeps.1:1
@@ -6121,7 +6121,7 @@ msgid ""
 msgstr ""
 "Die Liste der erstellten Dateien, die Teil des Uploads sind, der vorbereitet "
 "wird. B<dpkg-gencontrol> fügt die vermuteten Dateinamen von Binärpaketen "
-"hinzu, deren Steuerdateien es hier generiert.FIXME(en)"
+"hinzu, deren Steuerdateien es hier generiert."
 
 # type: TH
 #: ../../man/dpkg-name.1:6
@@ -7071,9 +7071,9 @@ msgstr ""
 "beginnen, werden aus der Datei entfernt. B<dpkg-shlibdeps> list die "
 "Informationen über die Abhängigkeiten von Laufzeitbibliotheken aus B<debian/"
 "shlibs.local>, B</etc/dpkg/shlibs.override>, der B<shlibs>-"
-"Steuerbereichsdatei (FIXME)(en) des Pakets, von dem B<objdump>(FIXME(en)) "
-"angibt, dass es die Bibliotheksabhängigkeit erfüllt oder B</etc/dpkg/shlibs."
-"default>. Der erste Treffer wird verwendet."
+"Steuerbereichsdatei des Pakets, von dem B<objdump> angibt, dass es die "
+"Bibliotheksabhängigkeit erfüllt oder B</etc/dpkg/shlibs.default>. Der erste "
+"Treffer wird verwendet."
 
 # type: Plain text
 #: ../../man/dpkg-shlibdeps.1:41
@@ -7262,9 +7262,9 @@ msgstr "dpkg-source"
 
 # type: TH
 #: ../../man/dpkg-source.1:2
-#, fuzzy, no-wrap
+#, no-wrap
 msgid "2007-09-24"
-msgstr "2007-01-24"
+msgstr "2007-09-24"
 
 # type: Plain text
 #: ../../man/dpkg-source.1:5
@@ -7347,9 +7347,9 @@ msgstr ""
 
 # type: Plain text
 #: ../../man/dpkg-source.1:44
-#, fuzzy, no-wrap
+#, no-wrap
 msgid "B<-b> I<directory> [I<orig-directory>|I<orig-targz>|'']"
-msgstr "B<-b> [I<Optionen>] I<Verzeichnis> [I<Orig-Verzeichnis>|I<Orig-targz>|'']"
+msgstr "B<-b> I<Verzeichnis> [I<Orig-Verzeichnis>|I<Orig-targz>|'']"
 
 # type: Plain text
 #: ../../man/dpkg-source.1:58
@@ -7409,7 +7409,6 @@ msgstr "Diese Option verneint ein vorher gesetztes B<-W>."
 
 # type: Plain text
 #: ../../man/dpkg-source.1:117
-#, fuzzy
 msgid ""
 "You may specify a perl regular expression to match files you want filtered "
 "out of the list of files for the diff. (This list is generated by a find "
@@ -7419,12 +7418,14 @@ msgid ""
 "can only be one active regexp, of multiple -i options only the last one will "
 "take effect."
 msgstr ""
-"Sie können einen regulären Ausdruck angeben, der auf Dateien passt, die Sie "
-"aus der Liste der Dateien für den Diff entfernen möchten; diese Liste wird "
-"von einem Find-Befehl generiert. B<-i> aktiviert diese Option mit der "
+"Sie können einen regulären Perl-Ausdruck angeben, der auf Dateien passt, die "
+"Sie aus der Liste der Dateien für den Diff entfernen möchten; diese Liste "
+"wird von einem Find-Befehl generiert. B<-i> aktiviert diese Option mit der "
 "Voreinstellung, dass die Steuerdateien und -Verzeichnisse der häufigsten "
 "Revisionskontrollsysteme, Backups, Swap-Dateien und Bau-Ausgabeverzeichnisse "
-"von Libtool herausgefiltert werden."
+"von Libtool herausgefiltert werden. Es kann nur einen aktiven regulären "
+"Ausdruck geben, von mehrfach angegebenen -i-Optionen wird nur die letzte "
+"berücksichtigt."
 
 # type: Plain text
 #: ../../man/dpkg-source.1:128
@@ -7442,13 +7443,12 @@ msgstr ""
 
 # type: TP
 #: ../../man/dpkg-source.1:128
-#, fuzzy, no-wrap
+#, no-wrap
 msgid "B<-I>[I<file-pattern>]"
-msgstr "B<-I>I<Dateiname>"
+msgstr "B<-I>[I<Dateimuster>]"
 
 # type: Plain text
 #: ../../man/dpkg-source.1:137
-#, fuzzy
 msgid ""
 "If this option is specified, the pattern will be passed to B<tar>(1)'s --"
 "exclude option when it is called to generate a .orig.tar.gz or .tar.gz file. "
@@ -7457,26 +7457,22 @@ msgid ""
 "patterns to exclude."
 msgstr ""
 "Falls diese Option angegeben wird, wird der Dateiname an die --exclude-"
-"Option von tar(FIXME(en)) weitergegeben, wenn es zur Erstellung der Datei ."
+"Option von B<tar>(1) weitergegeben, wenn es zur Erstellung der Datei ."
 "orig.tar.gz oder .tar.gz aufgerufen wird. Zum Beispiel führt -ICVS dazu, "
-"dass tar über CVS-Verzeichnisse hinweggeht, wenn es die tar.gz-Datei "
+"dass tar über CVS-Verzeichnisse hinweggeht, wenn es eine tar.gz-Datei "
 "erstellt. Diese Option kann mehrfach wiederholt werden, um mehrere "
 "Dateinamen aufzuführen, die ausgeschlossen werden sollen."
 
 # type: Plain text
 #: ../../man/dpkg-source.1:142
-#, fuzzy
 msgid ""
 "B<-I> by itself adds default --exclude options that will filter out control "
 "files and directories of the most common revision control systems, backup "
 "and swap files and Libtool build output directories."
 msgstr ""
-"Sie können einen regulären Ausdruck angeben, der auf Dateien passt, die Sie "
-"aus der Liste der Dateien für den Diff entfernen möchten; diese Liste wird "
-"von einem Find-Befehl generiert. B<-i> aktiviert diese Option mit der "
-"Voreinstellung, dass die Steuerdateien und -Verzeichnisse der häufigsten "
-"Revisionskontrollsysteme, Backups, Swap-Dateien und Bau-Ausgabeverzeichnisse "
-"von Libtool herausgefiltert werden."
+"B<i> fügt standardmäßig von Selbst --exclude-Optionen hinzu, die die "
+"Steuerdateien und -Verzeichnisse der häufigsten Revisionskontrollsysteme, "
+"Backups, Swap-Dateien und Bau-Ausgabeverzeichnisse von Libtool herausfiltern."
 
 # type: Plain text
 #: ../../man/dpkg-source.1:154
@@ -7497,6 +7493,8 @@ msgid ""
 "The default regexp and patterns for both options can be seen in the output "
 "of the B<--help> command."
 msgstr ""
+"Der voreingestellte reguläre Ausdruck und Muster für beide Optionen können in "
+"der Ausgabe des Befehls B<--help> gesehen werden."
 
 # type: TP
 #: ../../man/dpkg-source.1:157
@@ -7589,10 +7587,10 @@ msgid ""
 "and tarfile do not match a bad source archive will be generated."
 msgstr ""
 "Gibt an, dass die Originalquellen sowohl als Verzeichnis als auch als "
-"Tardatei verfügbar sind. FIXME(en) Es wird das Verzeichnis zur Erstellung "
-"des Diffs verwenden, aber die Tardatei für die B<.dsc>. Diese Option muss "
-"mit Vorsicht verwendet werden - falls das Verzeichnis und die Tardatei nicht "
-"zusammen passen, wird ein fehlerhaftes Quellarchiv erstellt."
+"Tardatei verfügbar sind. Es wird das Verzeichnis zur Erstellung des Diffs "
+"verwenden, aber die Tardatei für die B<.dsc>. Diese Option muss mit Vorsicht "
+"verwendet werden - falls das Verzeichnis und die Tardatei nicht zusammen "
+"passen, wird ein fehlerhaftes Quellarchiv erstellt."
 
 # type: TP
 #: ../../man/dpkg-source.1:197 ../../man/dpkg-source.1:242
@@ -8852,7 +8850,7 @@ msgstr ""
 # type: Plain text
 #: ../../man/dselect.1:182
 msgid "Installs selected packages."
-msgstr ""
+msgstr "Installiert ausgewählte Pakete."
 
 # type: Plain text
 #: ../../man/dselect.1:188
@@ -9451,13 +9449,13 @@ msgstr ""
 "Gibt den Dateinamen der Info-Datei an, deren Menüeintrag erstellt, "
 "aktualisiert oder entfernt werden soll. Falls B<--remove-exactly> angegeben "
 "wird, dann sollte I<Dateiname> der exakte Eintragsname sein, der entfernt "
-"werden soll (FIXME(en) d.h. »emacs-20/emacs« oder »gcc«), andernfalls wird "
-"der Basename des Dateinamens als Referenzierender des zu erstellenden "
-"Menüeintrags verwendet, es sei denn, es gibt einen überschreibenden START-"
-"INFO-DIR-Eintrag innerhalb der übergebenen Datei. Diese Datei muss daher im "
-"gleichen Verzeichnis wie die B<dir>-Datei existieren (oder gerade "
-"installiert werden, oder muss früher existiert haben, wenn ein Eintrag "
-"entfernt wird) (lesen Sie die Option B<--infodir>)."
+"werden soll (d.h. »emacs-20/emacs« oder »gcc«), andernfalls wird der Basename "
+"des Dateinamens als Referenzierender des zu erstellenden Menüeintrags "
+"verwendet, es sei denn, es gibt einen überschreibenden START-INFO-DIR-Eintrag "
+"innerhalb der übergebenen Datei. Diese Datei muss daher im gleichen "
+"Verzeichnis wie die B<dir>-Datei existieren (oder gerade installiert werden, "
+"oder muss früher existiert haben, wenn ein Eintrag entfernt wird) (lesen Sie "
+"die Option B<--infodir>)."
 
 # type: Plain text
 #: ../../man/install-info.8:64
@@ -11192,10 +11190,6 @@ msgstr ""
 "B<ln>(1), FHS, der Dateisystem Hierarchie-Standard (Filesystem Hierarchy "
 "Standard)."
 
-# type: TH
-#~ msgid "2007-08-31"
-#~ msgstr "2007-08-31"
-
 # type: Plain text
 #~ msgid ""
 #~ "This is very helpful in cutting out extraneous files that get included in "

File diff suppressed because it is too large
+ 522 - 127
man/po/pl.po


+ 4 - 0
po/ChangeLog

@@ -1,3 +1,7 @@
+2007-10-08  Robert Luberda  <robert@debian.org>
+
+	* pl.po: Updated to 929t.
+
 2007-09-19  Sunjae Park  <darehanl@gmail.com>
 
 	* ko.po: Updated to 929t.

+ 55 - 89
po/pl.po

@@ -4,18 +4,17 @@
 # Bartosz Feñski <fenio@debian.org>, 2004-2005
 # Robert Luberda <robert@debian.org>, 2006 - 2007
 msgid ""
-msgstr ""
-"Project-Id-Version: dpkg 1.14.6\n"
+msgstr "Project-Id-Version: dpkg 1.14.17\n"
 "Report-Msgid-Bugs-To: debian-dpkg@lists.debian.org\n"
 "POT-Creation-Date: 2007-08-18 03:58+0300\n"
-"PO-Revision-Date: 2007-08-13 23:24+0200\n"
+"PO-Revision-Date: 2007-10-08 22:30+0200\n"
 "Last-Translator: Robert Luberda <robert@debian.org>\n"
 "Language-Team: Polish <pddp@debian.linux.org.pl>\n"
-"MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=ISO-8859-2\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 ||"
+" n%100>=20) ? 1 : 2;\n"
+"MIME-Version: 1.0\n"
 "Content-Transfer-Encoding: 8-bit\n"
-"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
-"|| n%100>=20) ? 1 : 2;\n"
 
 #: lib/compat.c:46
 msgid "unable to open tmpfile for vsnprintf"
@@ -806,14 +805,14 @@ msgid "failed to read `%s' at line %d"
 msgstr "nie mo¿na odczytaæ `%s' w linii %d"
 
 #: lib/parsehelp.c:41
-#, fuzzy, c-format
+#, c-format
 msgid "warning, in file `%.255s' near line %d"
-msgstr "%s, w linii `%.255s' niedaleko linii %d"
+msgstr "ostrze¿enie, w pliku `%.255s' niedaleko linii %d"
 
 #: lib/parsehelp.c:44
-#, fuzzy, c-format
+#, c-format
 msgid "parse error, in file `%.255s' near line %d"
-msgstr "%s, w linii `%.255s' niedaleko linii %d"
+msgstr "b³±d parsowanie, w pliku `%.255s' niedaleko linii %d"
 
 #: lib/parsehelp.c:48
 #, c-format
@@ -909,30 +908,30 @@ msgid "error setting permissions of `%.255s'"
 msgstr "nie mo¿na zmieniæ uprawnieñ `%.255s'"
 
 #: src/archives.c:339
-#, fuzzy, c-format
+#, c-format
 msgid "failed to stat (dereference) existing symlink `%.250s'"
-msgstr "nie mo¿na ustawiæ praw do wykonywania `%.250s'"
+msgstr "nie mo¿na rozwi±zaæ dowi±zania symbolicznego `%.250s'"
 
 #: src/archives.c:360
 #, c-format
 msgid ""
 "failed to stat (dereference) proposed new symlink target `%.250s' for "
 "symlink `%.250s'"
-msgstr ""
+msgstr "nie mo¿na rozwi±zaæ proponowanego nowego celu dowi±zania symbolicznego `%.250s' dla dowi±zania `%.250s'"
 
 #: src/archives.c:411
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "trying to overwrite `%.250s', which is the diverted version of `"
 "%.250s' (package: %.100s)"
 msgstr ""
-"próba nadpisania `%.250s', który jest ominiêciem `%.250s'%.10s%.100s%.10s"
+"próba nadpisania `%.250s', który jest ominiêciem `%.250s' (pakiet %.100s)"
 
 #: src/archives.c:417
-#, fuzzy, c-format
+#, c-format
 msgid "trying to overwrite `%.250s', which is the diverted version of `%.250s'"
 msgstr ""
-"próba nadpisania `%.250s', który jest ominiêciem `%.250s'%.10s%.100s%.10s"
+"próba nadpisania `%.250s', który jest ominiêciem `%.250s'"
 
 #: src/archives.c:440
 #, c-format
@@ -1062,61 +1061,61 @@ msgid "unable to install new version of `%.255s'"
 msgstr "nie mo¿na zainstalowaæ nowej wersji `%.255s'"
 
 #: src/archives.c:853
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "dpkg: warning - ignoring dependency problem with %s:\n"
 "%s"
 msgstr ""
-"dpkg: ostrze¿enie - zignorowanie problemu z zale¿no¶ciami przy usuwaniu %s:\n"
+"dpkg: ostrze¿enie - zignorowanie problemu z zale¿no¶ciami w %s:\n"
 "%s"
 
 #: src/archives.c:860
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "dpkg: warning - considering deconfiguration of essential\n"
 " package %s, to enable %s.\n"
 msgstr ""
 "dpkg: ostrze¿enie - dekonfiguracja istotnego pakietu %s,\n"
-" aby usun±æ %s.\n"
+" aby w³±czyæ %s.\n"
 
 #: src/archives.c:864
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "dpkg: no, %s is essential, will not deconfigure\n"
 " it in order to enable %s.\n"
 msgstr ""
 "dpkg: niestety, %s jest istotnym pakietem, który nie zostanie\n"
-" zdekonfigurowany, aby usun±æ %s.\n"
+" zdekonfigurowany, aby w³±czyæ %s.\n"
 
 #: src/archives.c:878
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "dpkg: no, cannot proceed with %s (--auto-deconfigure will help):\n"
 "%s"
 msgstr ""
-"dpkg: niestety, nie mo¿na usun±æ %s (--auto-deconfigure mo¿e pomóc):\n"
+"dpkg: niestety, nie mo¿na kontynuowaæ przetwarzania %s (--auto-deconfigure mo¿e pomóc):\n"
 "%s"
 
 #: src/archives.c:888
-#, fuzzy, c-format
+#, c-format
 msgid "removal of %.250s"
-msgstr "nie mo¿na odczytaæ %.250s"
+msgstr "usuwanie %.250s"
 
 #: src/archives.c:915
-#, fuzzy, c-format
+#, c-format
 msgid "installation of %.250s"
-msgstr "nie mo¿na zainstalowaæ nowej wersji `%.255s'"
+msgstr "instalowanie %.250s"
 
 #: src/archives.c:916
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "dpkg: considering deconfiguration of %s, which would be broken by %s ...\n"
-msgstr "dpkg: usuwanie %s w zamian za %s ...\n"
+msgstr "dpkg: rozwa¿anie dekonfigurowania %s, który zosta³by popsuty przez %s ...\n"
 
 #: src/archives.c:923
-#, fuzzy, c-format
+#, c-format
 msgid "dpkg: yes, will deconfigure %s (broken by %s).\n"
-msgstr "dpkg: tak, %s zostanie usuniêty w zamian za %s.\n"
+msgstr "dpkg: tak, %s zostanie zdekonfigurowany (psuty przez %s).\n"
 
 #: src/archives.c:927 src/archives.c:1048
 #, c-format
@@ -1128,21 +1127,22 @@ msgstr ""
 "%s"
 
 #: src/archives.c:935
-#, fuzzy, c-format
+#, c-format
 msgid "dpkg: warning - ignoring breakage, may proceed anyway !\n"
-msgstr "dpkg: ostrze¿enie - zignorowanie konfliktu, dalsze przetwarzanie!\n"
+msgstr "dpkg: ostrze¿enie - zignorowanie psucia, dalsze przetwarzanie!\n"
 
 #: src/archives.c:941
 #, c-format
 msgid ""
 "installing %.250s would break %.250s, and\n"
 " deconfiguration is not permitted (--auto-deconfigure might help)"
-msgstr ""
+msgstr "instalacja %.250s popsuje %.250s, a\n"
+"nie pozwolono na dekonfiguracjê (--auto-deconfigure mo¿e pomóc)"
 
 #: src/archives.c:945
 #, c-format
 msgid "installing %.250s would break existing software"
-msgstr ""
+msgstr "instalacja %.250s zepsuje istniej±ce oprogramowanie"
 
 #: src/archives.c:978
 #, c-format
@@ -2709,19 +2709,19 @@ msgid "  Package %s is not installed.\n"
 msgstr "  Pakiet %s nie jest zainstalowany.\n"
 
 #: src/packages.c:362
-#, fuzzy, c-format
+#, c-format
 msgid " %s (%s) breaks %s and is %s.\n"
-msgstr "  %.250s dostarcza %.250s i jest %s.\n"
+msgstr " %s (%s) psuje %s i jest %s.\n"
 
 #: src/packages.c:370
-#, fuzzy, c-format
+#, c-format
 msgid "  %s (%s) provides %s.\n"
-msgstr "%s (podproces): %s\n"
+msgstr "%s (%s): dostarcza %s.\n"
 
 #: src/packages.c:375
-#, fuzzy, c-format
+#, c-format
 msgid "  Version of %s to be configured is %s.\n"
-msgstr "  Wersj± %s w systemie jest %s.\n"
+msgstr "  Wersj± %s do skonfigurowania jest %s.\n"
 
 #: src/packages.c:467
 msgid " depends on "
@@ -2852,14 +2852,14 @@ msgid "error trying to open %.250s"
 msgstr "nie mo¿na otworzyæ %.250s"
 
 #: src/processarc.c:405
-#, fuzzy, c-format
+#, c-format
 msgid "De-configuring %s, to allow removal of %s ...\n"
-msgstr "Dekonfiguracja %s, tak ¿e mo¿na usun±æ %s ...\n"
+msgstr "Dekonfigurowanie %s, tak ¿eby mo¿na by³o usun±æ %s ...\n"
 
 #: src/processarc.c:408
-#, fuzzy, c-format
+#, c-format
 msgid "De-configuring %s ...\n"
-msgstr "Usuwanie %s ...\n"
+msgstr "Dekonfigurowanie %s ...\n"
 
 #: src/processarc.c:479
 #, c-format
@@ -3018,24 +3018,24 @@ msgid "No packages found matching %s.\n"
 msgstr "Nie znaleziono pakietu pasuj±cego do wzorca %s.\n"
 
 #: src/query.c:254
-#, fuzzy, c-format
+#, c-format
 msgid "diversion by %s from: %s\n"
-msgstr "ominiêty przez %s do: %s\n"
+msgstr "ominiêcie przez %s z: %s\n"
 
 #: src/query.c:256
-#, fuzzy, c-format
+#, c-format
 msgid "diversion by %s to: %s\n"
-msgstr "ominiêty przez %s do: %s\n"
+msgstr "ominiêcie przez %s do: %s\n"
 
 #: src/query.c:259
-#, fuzzy, c-format
+#, c-format
 msgid "local diversion from: %s\n"
-msgstr "lokalne ominiêcie"
+msgstr "lokalne ominiêcie z: %s\n"
 
 #: src/query.c:260
-#, fuzzy, c-format
+#, c-format
 msgid "local diversion to: %s\n"
-msgstr "lokalnie ominiêty do %s\n"
+msgstr "lokalne ominiêcie do: %s\n"
 
 #: src/query.c:285
 msgid "--search needs at least one file name pattern argument"
@@ -5573,37 +5573,3 @@ msgstr "brakuj
 msgid "Serious problem: %s"
 msgstr "Powa¿ny problem: %s"
 
-#~ msgid "warning"
-#~ msgstr "ostrze¿enie"
-
-#~ msgid "parse error"
-#~ msgstr "b³±d sk³adni"
-
-#~ msgid " (package: "
-#~ msgstr " (pakiet: "
-
-#~ msgid ""
-#~ "dpkg: regarding %s containing %s:\n"
-#~ " package uses Breaks; not supported in this dpkg\n"
-#~ msgstr ""
-#~ "dpkg: odno¶nie do %s zawieraj±cego %s:\n"
-#~ " pakiet u¿ywa Przerwañ, czego ta wersja dpkg nie obs³uguje\n"
-
-#~ msgid "unsupported dependency problem - not installing %.250s"
-#~ msgstr ""
-#~ "nieobs³ugiwany problem z zale¿no¶ciami - %.250s nie bêdzie instalowany"
-
-#~ msgid "dpkg: warning - ignoring Breaks !\n"
-#~ msgstr "dpkg: ostrze¿enie - zignorowanie Przerwañ!\n"
-
-#~ msgid "diversion by %s"
-#~ msgstr "ominiêcie przez %s"
-
-#~ msgid "to"
-#~ msgstr "od"
-
-#~ msgid "from"
-#~ msgstr "do"
-
-#~ msgid "error reading %s"
-#~ msgstr "b³±d odczytu %s"

+ 50 - 0
scripts/Dpkg/ErrorHandling.pm

@@ -0,0 +1,50 @@
+package Dpkg::ErrorHandling;
+
+use Dpkg::Gettext;
+
+use base qw(Exporter);
+our @EXPORT_OK = qw( failure syserr error internerr warning
+                     warnerror subprocerr );
+
+our $warnable_error = 0;
+our $quiet_warnings = 0;
+our $progname = "unknown";
+
+sub failure { die sprintf(_g("%s: failure: %s"), $progname, $_[0])."\n"; }
+sub syserr { die sprintf(_g("%s: failure: %s: %s"), $progname, $_[0], $!)."\n"; }
+sub error { die sprintf(_g("%s: error: %s"), $progname, $_[0])."\n"; }
+sub internerr { die sprintf(_g("%s: internal error: %s"), $progname, $_[0])."\n"; }
+
+sub warning
+{
+    if (!$quiet_warnings) {
+	warn sprintf(_g("%s: warning: %s"), $progname, $_[0])."\n";
+    }
+}
+
+sub warnerror
+{
+    if ($warnable_error) {
+	warning(@_);
+    } else {
+	error(@_);
+    }
+}
+
+sub subprocerr {
+    my ($p) = @_;
+    require POSIX;
+    if (POSIX::WIFEXITED($?)) {
+	die sprintf(_g("%s: failure: %s gave error exit status %s"),
+		    $progname, $p, POSIX::WEXITSTATUS($?))."\n";
+    } elsif (POSIX::WIFSIGNALED($?)) {
+	die sprintf(_g("%s: failure: %s died from signal %s"),
+		    $progname, $p, POSIX::WTERMSIG($?))."\n";
+    } else {
+	die sprintf(_g("%s: failure: %s failed with unknown exit code %d"),
+		    $progname, $p, $?)."\n";
+    }
+}
+
+
+1;

+ 82 - 0
scripts/Dpkg/Path.pm

@@ -0,0 +1,82 @@
+# Copyright 2007 Raphaël Hertzog <hertzog@debian.org>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+package Dpkg::Path;
+
+use strict;
+use warnings;
+
+use Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT_OK = qw(get_pkg_root_dir relative_to_pkg_root);
+
+=head1 NAME
+
+Dpkg::Path - some common path handling functions
+
+=head1 DESCRIPTION
+
+It provides some functions to handle various path.
+
+=head1 METHODS
+
+=over 8
+
+=item get_pkg_root_dir($file)
+
+This function will scan upwards the hierarchy of directory to find out
+the directory which contains the "DEBIAN" sub-directory and it will return
+its path. This directory is the root directory of a package being built.
+
+=cut
+
+sub get_pkg_root_dir($) {
+    my $file = shift;
+    $file =~ s{/+$}{};
+    $file =~ s{/+[^/]+$}{} if not -d $file;
+    do {
+	return $file if -d "$file/DEBIAN";
+	last if $file !~ m{/};
+	$file =~ s{/+[^/]+$}{};
+    } while ($file);
+    return undef;
+}
+
+=item relative_to_pkg_root($file)
+
+Returns the filename relative to get_pkg_root_dir($file).
+
+=cut
+
+sub relative_to_pkg_root($) {
+    my $file = shift;
+    my $pkg_root = get_pkg_root_dir($file);
+    if (defined $pkg_root) {
+	$pkg_root .= "/";
+	return $file if ($file =~ s/^\Q$pkg_root\E//);
+    }
+    return undef;
+}
+
+=back
+
+=head1 AUTHOR
+
+Raphael Hertzog <hertzog@debian.org>.
+
+=cut
+
+1;

+ 92 - 0
scripts/Dpkg/Shlibs.pm

@@ -0,0 +1,92 @@
+# Copyright (C) 2007  Raphael Hertzog
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+package Dpkg::Shlibs;
+
+use strict;
+use warnings;
+
+use base qw(Exporter);
+our @EXPORT_OK = qw(@librarypaths find_library);
+
+use Dpkg::Gettext;
+use Dpkg::ErrorHandling qw(syserr);
+use Dpkg::Shlibs::Objdump;
+
+textdomain("dpkg-dev");
+
+use constant DEFAULT_LIBRARY_PATH =>
+    qw(/lib /usr/lib /lib32 /usr/lib32 /lib64 /usr/lib64
+       /emul/ia32-linux/lib /emul/ia32-linux/usr/lib);
+our @librarypaths = (DEFAULT_LIBRARY_PATH);
+
+# Update library paths with LD_LIBRARY_PATH
+if ($ENV{LD_LIBRARY_PATH}) {
+    foreach my $path (reverse split( /:/, $ENV{LD_LIBRARY_PATH} )) {
+	$path =~ s{/+$}{};
+	unless (scalar grep { $_ eq $path } @librarypaths) {
+	    unshift @librarypaths, $path;
+	}
+    }
+}
+
+# Update library paths with ld.so config
+parse_ldso_conf("/etc/ld.so.conf") if -e "/etc/ld.so.conf";
+
+my %visited;
+sub parse_ldso_conf {
+    my $file = shift;
+    open my $fh, "<", $file
+	or syserr(sprintf(_g("couldn't open %s"), $file));
+    $visited{$file}++;
+    while (<$fh>) {
+	next if /^\s*$/;
+	chomp;
+	s{/+$}{};
+	if (/^include\s+(\S.*\S)\s*$/) {
+	    foreach my $include (glob($1)) {
+		parse_ldso_conf($include) if -e $include
+		    && !$visited{$include};
+	    }
+	} elsif (m{^\s*/}) {
+	    s/^\s+//;
+	    my $libdir = $_;
+	    unless (scalar grep { $_ eq $libdir } @librarypaths) {
+		push @librarypaths, $libdir;
+	    }
+	}
+    }
+    close $fh or syserr(sprintf(_g("couldn't close %s"), $file));;
+}
+
+# find_library ($soname, \@rpath, $format, $root)
+sub find_library {
+    my ($lib, $rpath, $format, $root) = @_;
+    $root = "" if not defined($root);
+    $root =~ s{/+$}{};
+    my @rpath = @{$rpath};
+    foreach my $dir (@rpath, @librarypaths) {
+	if (-e "$root$dir/$lib") {
+	    my $libformat = Dpkg::Shlibs::Objdump::get_format("$root$dir/$lib");
+	    if ($format eq $libformat) {
+		return "$root$dir/$lib";
+	    }
+	}
+    }
+    return undef;
+}
+
+1;

+ 339 - 0
scripts/Dpkg/Shlibs/Objdump.pm

@@ -0,0 +1,339 @@
+# Copyright (C) 2007  Raphael Hertzog
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+use strict;
+use warnings;
+
+package Dpkg::Shlibs::Objdump;
+
+use Dpkg::Gettext;
+use Dpkg::ErrorHandling qw(syserr subprocerr warning);
+textdomain("dpkg-dev");
+
+sub new {
+    my $this = shift;
+    my $class = ref($this) || $this;
+    my $self = { 'objects' => {} };
+    bless $self, $class;
+    return $self;
+}
+
+sub parse {
+    my ($self, $file) = @_;
+    my $obj = Dpkg::Shlibs::Objdump::Object->new($file);
+
+    my $id = $obj->get_id;
+    if ($id) {
+	$self->{objects}{$id} = $obj;
+    }
+    return $id;
+}
+
+
+sub locate_symbol {
+    my ($self, $name) = @_;
+    foreach my $obj (values %{$self->{objects}}) {
+	my $sym = $obj->get_symbol($name);
+	if (defined($sym) && $sym->{defined}) {
+	    return $sym;
+	}
+    }
+    return undef;
+}
+
+sub get_object {
+    my ($self, $objid) = @_;
+    if (exists $self->{objects}{$objid}) {
+	return $self->{objects}{$objid};
+    }
+    return undef;
+}
+
+{
+    my %format; # Cache of result
+    sub get_format {
+	my ($file) = @_;
+
+	if (exists $format{$file}) {
+	    return $format{$file};
+	} else {
+	    local $ENV{LC_ALL} = "C";
+	    open(P, "-|", "objdump", "-a", "--", $file)
+		|| syserr(_g("cannot fork for objdump"));
+	    while (<P>) {
+		chomp;
+		if (/^\s*\S+:\s*file\s+format\s+(\S+)\s*$/) {
+		    $format{$file} = $1;
+		    return $format{$file};
+		}
+	    }
+	    close(P) or subprocerr(sprintf(_g("objdump on \`%s'"), $file));
+	}
+    }
+}
+
+sub is_elf {
+    my ($file) = @_;
+    open(FILE, "<", $file) ||
+	syserr(sprintf(_g("Can't open %s for test: %s"), $file, $!));
+    my ($header, $result) = ("", 0);
+    if (read(FILE, $header, 4) == 4) {
+	$result = 1 if ($header =~ /^\177ELF$/);
+    }
+    close(FILE);
+    return $result;
+}
+
+package Dpkg::Shlibs::Objdump::Object;
+
+use Dpkg::Gettext;
+use Dpkg::ErrorHandling qw(syserr warning);
+
+sub new {
+    my $this = shift;
+    my $file = shift || '';
+    my $class = ref($this) || $this;
+    my $self = {};
+    bless $self, $class;
+
+    $self->reset;
+    if ($file) {
+	$self->_read($file);
+    }
+
+    return $self;
+}
+
+sub reset {
+    my ($self) = @_;
+
+    $self->{file} = '';
+    $self->{id} = '';
+    $self->{SONAME} = '';
+    $self->{NEEDED} = [];
+    $self->{RPATH} = [];
+    $self->{dynsyms} = {};
+
+    return $self;
+}
+
+
+sub _read {
+    my ($self, $file) = @_;
+
+    $file ||= $self->{file};
+    return unless $file;
+
+    $self->reset;
+    $self->{file} = $file;
+
+    local $ENV{LC_ALL} = 'C';
+    open(my $objdump, "-|", "objdump", "-w", "-f", "-p", "-T", $file)
+	|| syserr(sprintf(_g("Can't execute objdump: %s"), $!));
+    my $ret = $self->_parse($objdump);
+    close($objdump);
+    return $ret;
+}
+
+sub _parse {
+    my ($self, $fh) = @_;
+
+    my $section = "none";
+    while (defined($_ = <$fh>)) {
+	chomp;
+	next if /^\s*$/;
+
+	if (/^DYNAMIC SYMBOL TABLE:/) {
+	    $section = "dynsym";
+	    next;
+	} elsif (/^Dynamic Section:/) {
+	    $section = "dyninfo";
+	    next;
+	} elsif (/^Program Header:/) {
+	    $section = "header";
+	    next;
+	} elsif (/^Version definitions:/) {
+	    $section = "verdef";
+	    next;
+	} elsif (/^Version References:/) {
+	    $section = "verref";
+	    next;
+	}
+
+	if ($section eq "dynsym") {
+	    $self->parse_dynamic_symbol($_);
+	} elsif ($section eq "dyninfo") {
+	    if (/^\s*NEEDED\s+(\S+)/) {
+		push @{$self->{NEEDED}}, $1;
+	    } elsif (/^\s*SONAME\s+(\S+)/) {
+		$self->{SONAME} = $1;
+	    } elsif (/^\s*HASH\s+(\S+)/) {
+		$self->{HASH} = $1;
+	    } elsif (/^\s*GNU_HASH\s+(\S+)/) {
+		$self->{GNU_HASH} = $1;
+	    } elsif (/^\s*RPATH\s+(\S+)/) {
+		push @{$self->{RPATH}}, split (/:/, $1);
+	    }
+	} elsif ($section eq "none") {
+	    if (/^\s*\S+:\s*file\s+format\s+(\S+)\s*$/) {
+		$self->{format} = $1;
+	    } elsif (/^architecture:\s*\S+,\s*flags\s*\S+:\s*$/) {
+		# Parse 2 lines of "-f"
+		# architecture: i386, flags 0x00000112:
+		# EXEC_P, HAS_SYMS, D_PAGED
+		# start address 0x08049b50
+		$_ = <$fh>;
+		chomp;
+		$self->{flags}{$_} = 1 foreach (split(/,\s*/));
+	    }
+	}
+    }
+
+    return $section ne "none";
+}
+
+# Output format of objdump -w -T
+#
+# /lib/libc.so.6:     file format elf32-i386
+#
+# DYNAMIC SYMBOL TABLE:
+# 00056ef0 g    DF .text  000000db  GLIBC_2.2   getwchar
+# 00000000 g    DO *ABS*  00000000  GCC_3.0     GCC_3.0
+# 00069960  w   DF .text  0000001e  GLIBC_2.0   bcmp
+# 00000000  w   D  *UND*  00000000              _pthread_cleanup_pop_restore
+# 0000b788 g    DF .text  0000008e  Base        .protected xine_close
+# 0000b788 g    DF .text  0000008e              .hidden IA__g_free
+# |        ||||||| |      |         |           |
+# |        ||||||| |      |         Version str (.visibility) + Symbol name
+# |        ||||||| |      Alignment
+# |        ||||||| Section name (or *UND* for an undefined symbol)
+# |        ||||||F=Function,f=file,O=object
+# |        |||||d=debugging,D=dynamic
+# |        ||||I=Indirect
+# |        |||W=warning
+# |        ||C=constructor
+# |        |w=weak
+# |        g=global,l=local,!=both global/local
+# Size of the symbol
+#
+# GLIBC_2.2 is the version string associated to the symbol
+# (GLIBC_2.2) is the same but the symbol is hidden, a newer version of the
+# symbol exist
+
+sub parse_dynamic_symbol {
+    my ($self, $line) = @_;
+    my $vis_re = '(\.protected|\.hidden|\.internal|0x\S+)';
+    if ($line =~ /^[0-9a-f]+ (.{7})\s+(\S+)\s+[0-9a-f]+\s+(\S+)?(?:(?:\s+$vis_re)?\s+(\S+))/) {
+
+	my ($flags, $sect, $ver, $vis, $name) = ($1, $2, $3, $4, $5);
+
+	# Special case if version is missing but extra visibility
+	# attribute replaces it in the match
+	if (defined($ver) and $ver =~ /^$vis_re$/) {
+	    $vis = $ver;
+	    $ver = '';
+	}
+
+	# Cleanup visibility field
+	$vis =~ s/^\.// if defined($vis);
+
+	my $symbol = {
+		name => $name,
+		version => defined($ver) ? $ver : '',
+		section => $sect,
+		dynamic => substr($flags, 5, 1) eq "D",
+		debug => substr($flags, 5, 1) eq "d",
+		type => substr($flags, 6, 1),
+		weak => substr($flags, 1, 1) eq "w",
+		local => substr($flags, 0, 1) eq "l",
+		global => substr($flags, 0, 1) eq "g",
+		visibility => defined($vis) ? $vis : '',
+		hidden => '',
+		defined => $sect ne '*UND*'
+	    };
+
+	# Handle hidden symbols
+	if (defined($ver) and $ver =~ /^\((.*)\)$/) {
+	    $ver = $1;
+	    $symbol->{version} = $1;
+	    $symbol->{hidden} = 1;
+	}
+
+	# Register symbol
+	$self->add_dynamic_symbol($symbol);
+    } elsif ($line =~ /^[0-9a-f]+ (.{7})\s+(\S+)\s+[0-9a-f]+/) {
+	# Same start but no version and no symbol ... just ignore
+    } elsif ($line =~ /^REG_G\d+\s+/) {
+	# Ignore some s390-specific output like
+	# REG_G6           g     R *UND*      0000000000000000              #scratch
+    } else {
+	warning(sprintf(_g("Couldn't parse dynamic symbol definition: %s"), $line));
+    }
+}
+
+
+sub add_dynamic_symbol {
+    my ($self, $symbol) = @_;
+    $symbol->{soname} = $self->{SONAME};
+    if ($symbol->{version}) {
+	$self->{dynsyms}{$symbol->{name} . '@' . $symbol->{version}} = $symbol;
+    } else {
+	$self->{dynsyms}{$symbol->{name}} = $symbol;
+    }
+}
+
+sub get_id {
+    my $self = shift;
+    return $self->{SONAME} || $self->{file};
+}
+
+sub get_symbol {
+    my ($self, $name) = @_;
+    if (exists $self->{dynsyms}{$name}) {
+	return $self->{dynsyms}{$name};
+    }
+    return undef;
+}
+
+sub get_exported_dynamic_symbols {
+    my ($self) = @_;
+    return grep { $_->{defined} && $_->{dynamic} && !$_->{local} }
+	    values %{$self->{dynsyms}};
+}
+
+sub get_undefined_dynamic_symbols {
+    my ($self) = @_;
+    return grep { (!$_->{defined}) && $_->{dynamic} }
+	    values %{$self->{dynsyms}};
+}
+
+sub get_needed_libraries {
+    my $self = shift;
+    return @{$self->{NEEDED}};
+}
+
+sub is_executable {
+    my $self = shift;
+    return exists $self->{flags}{EXEC_P} and $self->{flags}{EXEC_P};
+}
+
+sub is_public_library {
+    my $self = shift;
+    return exists $self->{flags}{DYNAMIC} and $self->{flags}{DYNAMIC}
+	and exists $self->{SONAME} and $self->{SONAME};
+}
+
+1;

+ 326 - 0
scripts/Dpkg/Shlibs/SymbolFile.pm

@@ -0,0 +1,326 @@
+# Copyright (C) 2007  Raphael Hertzog
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+package Dpkg::Shlibs::SymbolFile;
+
+use Dpkg::Gettext;
+use Dpkg::ErrorHandling qw(syserr warning error);
+use Dpkg::Version qw(vercmp);
+textdomain("dpkg-dev");
+
+my %blacklist = (
+    '__bss_end__' => 1,		# arm
+    '__bss_end' => 1,		# arm
+    '_bss_end__' => 1,		# arm
+    '__bss_start' => 1,		# ALL
+    '__bss_start__' => 1,	# arm
+    '__data_start' => 1,	# arm
+    '__do_global_ctors_aux' => 1,   # ia64
+    '__do_global_dtors_aux' => 1,   # ia64
+    '__do_jv_register_classes' => 1,# ia64
+    '_DYNAMIC' => 1,		# ALL
+    '_edata' => 1,		# ALL
+    '_end' => 1,		# ALL
+    '__end__' => 1,		# arm
+    '_fbss' => 1,		# mips, mipsel
+    '_fdata' => 1,		# mips, mipsel
+    '_fini' => 1,		# ALL
+    '_ftext' => 1,		# mips, mipsel
+    '_GLOBAL_OFFSET_TABLE_' => 1,   # hppa, mips, mipsel
+    '__gmon_start__' => 1,	# hppa
+    '_gp' => 1,			# mips, mipsel
+    '_init' => 1,		# ALL
+    '_PROCEDURE_LINKAGE_TABLE_' => 1, # sparc, alpha
+    '_SDA2_BASE_' => 1,		# powerpc
+    '_SDA_BASE_' => 1,		# powerpc
+);
+
+for (my $i = 14; $i <= 31; $i++) {
+    # Many powerpc specific symbols
+    $blacklist{"_restfpr_$i"} = 1;
+    $blacklist{"_restfpr_$i\_x"} = 1;
+    $blacklist{"_restgpr_$i"} = 1;
+    $blacklist{"_restgpr_$i\_x"} = 1;
+    $blacklist{"_savefpr_$i"} = 1;
+    $blacklist{"_savegpr_$i"} = 1;
+}
+
+sub new {
+    my $this = shift;
+    my $file = shift;
+    my $class = ref($this) || $this;
+    my $self = { };
+    bless $self, $class;
+    if (defined($file) ) {
+	$self->{file} = $file;
+	$self->load($file) if -e $file;
+    }
+    return $self;
+}
+
+sub clear {
+    my ($self) = @_;
+    $self->{objects} = {};
+}
+
+sub clear_except {
+    my ($self, @ids) = @_;
+    my %has;
+    $has{$_} = 1 foreach (@ids);
+    foreach my $objid (keys %{$self->{objects}}) {
+	delete $self->{objects}{$objid} unless exists $has{$objid};
+    }
+}
+
+# Parameter seen is only used for recursive calls
+sub load {
+    my ($self, $file, $seen) = @_;
+
+    if (defined($seen)) {
+	return if exists $seen->{$file}; # Avoid include loops
+    } else {
+	$self->{file} = $file;
+	$seen = {};
+    }
+    $seen->{$file} = 1;
+
+    open(my $sym_file, "<", $file)
+	|| syserr(sprintf(_g("Can't open %s: %s"), $file));
+    my ($object);
+    while (defined($_ = <$sym_file>)) {
+	chomp($_);
+	if (/^\s+(\S+)\s(\S+)(?:\s(\d+))?/) {
+	    if (not defined ($object)) {
+		error(sprintf(_g("Symbol information must be preceded by a header (file %s, line %s).", $file, $.)));
+	    }
+	    # New symbol
+	    my $sym = {
+		minver => $2,
+		dep_id => defined($3) ? $3 : 0,
+		deprecated => 0
+	    };
+	    $self->{objects}{$object}{syms}{$1} = $sym;
+	} elsif (/^#include\s+"([^"]+)"/) {
+	    my $filename = $1;
+	    my $dir = $file;
+	    $dir =~ s{[^/]+$}{}; # Strip filename
+	    $self->load("$dir$filename", $seen);
+	} elsif (/^#DEPRECATED: ([^#]+)#\s*(\S+)\s(\S+)(?:\s(\d+))?/) {
+	    my $sym = {
+		minver => $3,
+		dep_id => defined($4) ? $4 : 0,
+		deprecated => $1
+	    };
+	    $self->{objects}{$object}{syms}{$2} = $sym;
+	} elsif (/^#/) {
+	    # Skip possible comments
+	} elsif (/^\|\s*(.*)$/) {
+	    # Alternative dependency template
+	    push @{$self->{objects}{$object}{deps}}, "$1";
+	} elsif (/^(\S+)\s+(.*)$/) {
+	    # New object and dependency template
+	    $object = $1;
+	    if (exists $self->{objects}{$object}) {
+		# Update/override infos only
+		$self->{objects}{$object}{deps} = [ "$2" ];
+	    } else {
+		# Create a new object
+		$self->{objects}{$object} = {
+		    syms => {},
+		    deps => [ "$2" ]
+		};
+	    }
+	} else {
+	    warning(sprintf(_g("Failed to parse a line in %s: %s"), $file, $_));
+	}
+    }
+    close($sym_file);
+}
+
+sub save {
+    my ($self, $file, $with_deprecated) = @_;
+    $file = $self->{file} unless defined($file);
+    my $fh;
+    if ($file eq "-") {
+	$fh = \*STDOUT;
+    } else {
+	open($fh, ">", $file)
+	    || syserr(sprintf(_g("Can't open %s for writing: %s"), $file, $!));
+    }
+    $self->dump($fh, $with_deprecated);
+    close($fh) if ($file ne "-");
+}
+
+sub dump {
+    my ($self, $fh, $with_deprecated) = @_;
+    $with_deprecated = 1 unless defined($with_deprecated);
+    foreach my $soname (sort keys %{$self->{objects}}) {
+	print $fh "$soname $self->{objects}{$soname}{deps}[0]\n";
+	print $fh "| $_" foreach (@{$self->{objects}{$soname}{deps}}[ 1 .. -1 ]);
+	foreach my $sym (sort keys %{$self->{objects}{$soname}{syms}}) {
+	    my $info = $self->{objects}{$soname}{syms}{$sym};
+	    next if $info->{deprecated} and not $with_deprecated;
+	    print $fh "#DEPRECATED: $info->{deprecated}#" if $info->{deprecated};
+	    print $fh " $sym $info->{minver}";
+	    print $fh " $info->{dep_id}" if $info->{dep_id};
+	    print $fh "\n";
+	}
+    }
+}
+
+# merge_symbols($object, $minver)
+# Needs $Objdump->get_object($soname) as parameter
+# Don't merge blacklisted symbols related to the internal (arch-specific)
+# machinery
+sub merge_symbols {
+    my ($self, $object, $minver) = @_;
+    my $soname = $object->{SONAME} || error(_g("Can't merge symbols from objects without SONAME."));
+    my %dynsyms;
+    foreach my $sym ($object->get_exported_dynamic_symbols()) {
+	next if exists $blacklist{$sym->{name}};
+	if ($sym->{version}) {
+	    $dynsyms{$sym->{name} . '@' . $sym->{version}} = $sym;
+	} else {
+	    $dynsyms{$sym->{name}} = $sym;
+	}
+    }
+
+    unless ($self->{objects}{$soname}) {
+	$self->create_object($soname, '');
+    }
+    # Scan all symbols provided by the objects
+    foreach my $sym (keys %dynsyms) {
+	if (exists $self->{objects}{$soname}{syms}{$sym}) {
+	    # If the symbol is already listed in the file
+	    my $info = $self->{objects}{$soname}{syms}{$sym};
+	    if ($info->{deprecated}) {
+		# Symbol reappeared somehow
+		$info->{deprecated} = 0;
+		$info->{minver} = $minver;
+		next;
+	    }
+	    # We assume that the right dependency information is already
+	    # there.
+	    if (vercmp($minver, $info->{minver}) < 0) {
+		$info->{minver} = $minver;
+	    }
+	} else {
+	    # The symbol is new and not present in the file
+	    my $info = {
+		minver => $minver,
+		deprecated => 0,
+		dep_id => 0
+	    };
+	    $self->{objects}{$soname}{syms}{$sym} = $info;
+	}
+    }
+
+    # Scan all symbols in the file and mark as deprecated those that are
+    # no more provided (only if the minver is bigger than the version where
+    # the symbol was introduced)
+    foreach my $sym (keys %{$self->{objects}{$soname}{syms}}) {
+	if (! exists $dynsyms{$sym}) {
+	    my $info = $self->{objects}{$soname}{syms}{$sym};
+	    if (vercmp($minver, $info->{minver}) > 0) {
+		$self->{objects}{$soname}{syms}{$sym}{deprecated} = $minver;
+	    }
+	}
+    }
+}
+
+sub is_empty {
+    my ($self) = @_;
+    return scalar(keys %{$self->{objects}}) ? 0 : 1;
+}
+
+sub has_object {
+    my ($self, $soname) = @_;
+    return exists $self->{objects}{$soname};
+}
+
+sub create_object {
+    my ($self, $soname, @deps) = @_;
+    $self->{objects}{$soname} = {
+	syms => {},
+	deps => [ @deps ]
+    };
+}
+
+sub get_dependency {
+    my ($self, $soname, $dep_id) = @_;
+    $dep_id = 0 unless defined($dep_id);
+    return $self->{objects}{$soname}{deps}[$dep_id];
+}
+
+sub lookup_symbol {
+    my ($self, $name, $sonames, $inc_deprecated) = @_;
+    $inc_deprecated = 0 unless defined($inc_deprecated);
+    foreach my $so (@{$sonames}) {
+	next if (! exists $self->{objects}{$so});
+	if (exists $self->{objects}{$so}{syms}{$name} and
+	    ($inc_deprecated or not
+	    $self->{objects}{$so}{syms}{$name}{deprecated}))
+	{
+	    my $dep_id = $self->{objects}{$so}{syms}{$name}{dep_id};
+	    return {
+		'depends' => $self->{objects}{$so}{deps}[$dep_id],
+		'soname' => $so,
+		%{$self->{objects}{$so}{syms}{$name}}
+	    };
+	}
+    }
+    return undef;
+}
+
+sub has_new_symbols {
+    my ($self, $ref) = @_;
+    foreach my $soname (keys %{$self->{objects}}) {
+	my $mysyms = $self->{objects}{$soname}{syms};
+	next if not exists $ref->{objects}{$soname};
+	my $refsyms = $ref->{objects}{$soname}{syms};
+	foreach my $sym (grep { not $mysyms->{$_}{deprecated} }
+	    keys %{$mysyms})
+	{
+	    if ((not exists $refsyms->{$sym}) or
+		$refsyms->{$sym}{deprecated})
+	    {
+		return 1;
+	    }
+	}
+    }
+    return 0;
+}
+
+sub has_lost_symbols {
+    my ($self, $ref) = @_;
+    return $ref->has_new_symbols($self);
+}
+
+
+sub has_new_libs {
+    my ($self, $ref) = @_;
+    foreach my $soname (keys %{$self->{objects}}) {
+	return 1 if not exists $ref->{objects}{$soname};
+    }
+    return 0;
+}
+
+sub has_lost_libs {
+    my ($self, $ref) = @_;
+    return $ref->has_new_libs($self);
+}
+
+1;

+ 2 - 1
scripts/Dpkg/Source/VCS/git.pm

@@ -176,7 +176,8 @@ sub prep_tar {
 
 	# As an optimisation, remove the index. It will be recreated by git
 	# reset during unpack. It's probably small, but you never know, this
-	# might save a lot of space.
+	# might save a lot of space. (Also, the index file may not be
+	# portable.)
 	unlink(".git/index"); # error intentionally ignored
 	
 	chdir($old_cwd) ||

+ 205 - 0
scripts/Dpkg/Version.pm

@@ -0,0 +1,205 @@
+# Copyright Colin Watson <cjwatson@debian.org>
+# Copyright Ian Jackson <iwj@debian.org>
+# Copyright 2007 by Don Armstrong <don@donarmstrong.com>.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+package Dpkg::Version;
+
+use strict;
+use warnings;
+
+use Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT_OK = qw(vercmp);
+
+=head1 NAME
+
+Dpkg::Version - pure-Perl dpkg-style version comparison
+
+=head1 DESCRIPTION
+
+The Dpkg::Version module provides pure-Perl routines to compare
+dpkg-style version numbers, as used in Debian packages. If you have the
+libapt-pkg Perl bindings available (Debian package libapt-pkg-perl), they
+may offer better performance.
+
+=head1 METHODS
+
+=over 8
+
+=cut
+
+sub parseversion ($)
+{
+    my $ver = shift;
+    my %verhash;
+    if ($ver =~ /:/)
+    {
+	$ver =~ /^(\d+):(.+)/ or die "bad version number '$ver'";
+	$verhash{epoch} = $1;
+	$ver = $2;
+    }
+    else
+    {
+	$verhash{epoch} = 0;
+    }
+    if ($ver =~ /(.+)-(.+)$/)
+    {
+	$verhash{version} = $1;
+	$verhash{revision} = $2;
+    }
+    else
+    {
+	$verhash{version} = $ver;
+	$verhash{revision} = 0;
+    }
+    return %verhash;
+}
+
+# verrevcmp
+
+# This function is almost exactly equivalent
+# to dpkg's verrevcmp function, including the
+# order subroutine which it uses.
+
+sub verrevcmp($$)
+{
+
+     sub order{
+	  my ($x) = @_;
+	  ##define order(x) ((x) == '~' ? -1 \
+	  #           : cisdigit((x)) ? 0 \
+	  #           : !(x) ? 0 \
+	  #           : cisalpha((x)) ? (x) \
+	  #           : (x) + 256)
+	  # This comparison is out of dpkg's order to avoid
+	  # comparing things to undef and triggering warnings.
+	  if (not defined $x) {
+	       return 0;
+	  }
+	  elsif ($x eq '~') {
+	       return -1;
+	  }
+	  elsif ($x =~ /^\d$/) {
+	       return 0;
+	  }
+	  elsif ($x =~ /^[A-Z]$/i) {
+	       return ord($x);
+	  }
+	  else {
+	       return ord($x) + 256;
+	  }
+     }
+
+     sub next_elem(\@){
+	  my $a = shift;
+	  return @{$a} ? shift @{$a} : undef;
+     }
+     my ($val, $ref) = @_;
+     $val = "" if not defined $val;
+     $ref = "" if not defined $ref;
+     my @val = split //,$val;
+     my @ref = split //,$ref;
+     my $vc = next_elem @val;
+     my $rc = next_elem @ref;
+     while (defined $vc or defined $rc) {
+	  my $first_diff = 0;
+	  while ((defined $vc and $vc !~ /^\d$/) or
+		 (defined $rc and $rc !~ /^\d$/)) {
+	       my $vo = order($vc); my $ro = order($rc);
+	       # Unlike dpkg's verrevcmp, we only return 1 or -1 here.
+	       return (($vo - $ro > 0) ? 1 : -1) if $vo != $ro;
+	       $vc = next_elem @val; $rc = next_elem @ref;
+	  }
+	  while (defined $vc and $vc eq '0') {
+	       $vc = next_elem @val;
+	  }
+	  while (defined $rc and $rc eq '0') {
+	       $rc = next_elem @ref;
+	  }
+	  while (defined $vc and $vc =~ /^\d$/ and
+		 defined $rc and $rc =~ /^\d$/) {
+	       $first_diff = ord($vc) - ord($rc) if !$first_diff;
+	       $vc = next_elem @val; $rc = next_elem @ref;
+	  }
+	  return 1 if defined $vc and $vc =~ /^\d$/;
+	  return -1 if defined $rc and $rc =~ /^\d$/;
+	  return $first_diff if $first_diff;
+     }
+     return 0;
+}
+
+=item vercmp
+
+Compare the two arguments as dpkg-style version numbers. Returns -1 if the
+first argument represents a lower version number than the second, 1 if the
+first argument represents a higher version number than the second, and 0 if
+the two arguments represent equal version numbers.
+
+=cut
+
+sub vercmp ($$)
+{
+    my %version = parseversion $_[0];
+    my %refversion = parseversion $_[1];
+    return 1 if $version{epoch} > $refversion{epoch};
+    return -1 if $version{epoch} < $refversion{epoch};
+    my $r = verrevcmp($version{version}, $refversion{version});
+    return $r if $r;
+    return verrevcmp($version{revision}, $refversion{revision});
+}
+
+=item compare_versions
+
+Emulates dpkg --compare-versions. Takes two versions as arguments
+one and three and one operator as argument two. Supports the following
+operators: 'gt', 'ge', 'eq', 'le', 'lt', and '>>', '>=', '=', '<=', '<<'.
+Returns a true value if the specified condition is true, a false value
+otherwise.
+
+=cut
+
+sub compare_versions ($$$)
+{
+    my $rel = $_[1];
+    my $res = vercmp($_[0], $_[2]);
+
+    if ($rel eq 'gt' or $rel =~ />?>/) {
+	return $res > 0;
+    } elsif ($rel eq 'ge' or $rel eq '>=') {
+	return $res >= 0;
+    } elsif ($rel eq 'eq' or $rel eq '=') {
+	return $res == 0;
+    } elsif ($rel eq 'le' or $rel eq '<=') {
+	return $res <= 0;
+    } elsif ($rel eq 'lt' or $rel =~ /<?</) {
+	return $res < 0;
+    } else {
+	die "bad relation '$rel'";
+    }
+}
+
+=back
+
+=head1 AUTHOR
+
+Don Armstrong <don@donarmstrong.com> and Colin Watson
+E<lt>cjwatson@debian.orgE<gt>, based on the implementation in
+C<dpkg/lib/vercmp.c> by Ian Jackson and others.
+
+=cut
+
+1;

+ 38 - 2
scripts/Makefile.am

@@ -10,6 +10,7 @@ bin_SCRIPTS = \
 	dpkg-distaddfile \
 	dpkg-genchanges \
 	dpkg-gencontrol \
+	dpkg-gensymbols \
 	dpkg-name \
 	dpkg-parsechangelog \
 	dpkg-scanpackages \
@@ -36,6 +37,7 @@ EXTRA_DIST = \
 	dpkg-distaddfile.pl \
 	dpkg-genchanges.pl \
 	dpkg-gencontrol.pl \
+	dpkg-gensymbols.pl \
 	dpkg-name.sh \
 	dpkg-parsechangelog.pl \
 	dpkg-scanpackages.pl \
@@ -47,7 +49,22 @@ EXTRA_DIST = \
 	dpkg-statoverride.pl \
 	install-info.pl \
 	update-alternatives.pl \
-	changelog/debian.pl
+	changelog/debian.pl \
+	t/000_pod.t \
+	t/100_Dpkg_Version.t \
+	t/200_Dpkg_Shlibs.t \
+	t/200_Dpkg_Shlibs/symbols.fake-1 \
+	t/200_Dpkg_Shlibs/symbols.fake-2 \
+	t/200_Dpkg_Shlibs/symbols.include-1 \
+	t/200_Dpkg_Shlibs/symbols.include-2 \
+	t/200_Dpkg_Shlibs/ld.so.conf \
+	t/200_Dpkg_Shlibs/ld.so.conf_2 \
+	t/200_Dpkg_Shlibs/ld.so.conf.d/normal.conf \
+	t/200_Dpkg_Shlibs/ld.so.conf.d/inf_recurse.conf \
+	t/200_Dpkg_Shlibs/ld.so.conf.d/recursive.conf \
+	t/200_Dpkg_Shlibs/objdump.glib-ia64 \
+	t/200_Dpkg_Shlibs/objdump.libc6-2.3 \
+	t/200_Dpkg_Shlibs/objdump.libc6-2.6
 
 CLEANFILES = \
 	$(bin_SCRIPTS) $(sbin_SCRIPTS) $(changelog_SCRIPTS) \
@@ -55,9 +72,15 @@ CLEANFILES = \
 
 perllibdir = $(PERL_LIBDIR)
 nobase_dist_perllib_DATA = \
-	Dpkg/Source/VCS/git.pm \
+	Dpkg/Shlibs.pm \
+	Dpkg/Shlibs/Objdump.pm \
+	Dpkg/Shlibs/SymbolFile.pm \
+	Dpkg/ErrorHandling.pm \
 	Dpkg/BuildOptions.pm \
 	Dpkg/Gettext.pm \
+	Dpkg/Path.pm \
+	Dpkg/Version.pm \
+	Dpkg/Source/VCS/git.pm \
 	Dpkg.pm
 
 dist_pkglib_SCRIPTS = \
@@ -110,3 +133,16 @@ install-data-hook:
 uninstall-local:
 	rm -f $(DESTDIR)$(sysconfdir)/alternatives/README
 	rm -f $(DESTDIR)$(sbindir)/install-info
+
+TEST_FILES= $(srcdir)/t/*.t
+TEST_VERBOSE= 0
+
+clean-local:
+	chmod -R +w t.tmp
+	rm -fr t.tmp
+
+check: $(TEST_FILES) $(wildcard $(srcdir)/t/200_Dpkg_Shlibs/ld.so.conf*)
+# a bit hacky...
+	$(mkdir_p) t.tmp
+	cp -dRl $(srcdir)/t/200_Dpkg_Shlibs/ld.so.conf* t.tmp/
+	srcdir=$(srcdir) PERL_DL_NONLAZY=1 $(PERL) -I$(srcdir) "-MExtUtils::Command::MM" "-e" "test_harness($(TEST_VERBOSE), '.')" $(TEST_FILES)

+ 8 - 4
scripts/dpkg-buildpackage.pl

@@ -59,13 +59,15 @@ Options:
   -si (default)  src includes orig for rev. 0 or 1.    }
   -sa            uploaded src always includes orig.    }
   -sd            uploaded src is diff and .dsc only.   }
-  -sn            force Debian native source format.      } only passed
-  -s[sAkurKUR]   see dpkg-source for explanation.        } to dpkg-source
+  -sn            force Debian native source format.      }
+  -s[sAkurKUR]   see dpkg-source for explanation.        } only passed
+  -z<level>      compression level of source             } to dpkg-source
+  -Z(gz|bz2|lzma) compression to use for source          }
   -nc            do not clean source tree (implies -b).
   -tc            clean source tree when finished.
   -ap            add pause before starting signature process.
-  -W             turn certain errors into warnings.       } passed to
-  -E             when -W is turned on, -E turns it off.   } dpkg-source
+  -E             turn certain warnings into errors.       } passed to
+  -W             when -E is turned on, -W turns it off.   } dpkg-source
   -i[<regex>]    ignore diffs of files matching regex.    } only passed
   -I[<pattern>]  filter out files when building tarballs. } to dpkg-source
   --admindir=<directory>
@@ -141,6 +143,8 @@ while (@ARGV) {
 	$sourcestyle = $_;
     } elsif (/^-s[nsAkurKUR]$/) {
 	push @passopts, $_; # passed to dpkg-source
+    } elsif (/^-[zZ]/) {
+	push @passopts, $_; # passed to dpkg-source
     } elsif (/^-i.*$/) {
 	$diffignore = $_;
     } elsif (/^-I.*$/) {

+ 234 - 0
scripts/dpkg-gensymbols.pl

@@ -0,0 +1,234 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Dpkg;
+use Dpkg::Shlibs qw(@librarypaths);
+use Dpkg::Shlibs::Objdump;
+use Dpkg::Shlibs::SymbolFile;
+use Dpkg::Gettext;
+
+textdomain("dpkg-dev");
+
+push(@INC, $dpkglibdir);
+require 'controllib.pl';
+
+our (%f, %fi);
+our %p2i;
+our @librarypaths;
+
+our $host_arch= `dpkg-architecture -qDEB_HOST_ARCH`;
+chomp $host_arch;
+
+my $controlfile = 'debian/control';
+my $changelogfile = 'debian/changelog';
+my $packagebuilddir = 'debian/tmp';
+
+my $sourceversion;
+my $stdout;
+my $oppackage;
+my $compare = 1; # Bail on missing symbols by default
+my $output;
+my $debug = 0;
+
+sub version {
+    printf _g("Debian %s version %s.\n"), $progname, $version;
+
+    printf _g("
+Copyright (C) 2007 Raphael Hertzog.
+");
+
+    printf _g("
+This is free software; see the GNU General Public Licence version 2 or
+later for copying conditions. There is NO warranty.
+");
+}
+
+sub usage {
+    printf _g(
+"Usage: %s [<option> ...]
+
+Options:
+  -p<package>              generate symbols file for package.
+  -P<packagebuilddir>      temporary build dir instead of debian/tmp.
+  -e<library>              explicitely list libraries to scan.
+  -v<version>              version of the packages (defaults to
+                           version extracted from debian/changelog).
+  -c<level>                compare generated symbols file with the
+                           reference file in the debian directory.
+			   Fails if difference are too important
+			   (level goes from 0 for no check, to 4
+			   for all checks). By default checks at
+			   level 1.
+  -O<file>                 write to <file>, not .../DEBIAN/symbols.
+  -O                       write to stdout, not .../DEBIAN/symbols.
+  -d                       display debug information during work.
+  -h, --help               show this help message.
+      --version            show the version.
+"), $progname;
+}
+
+my @files;
+while (@ARGV) {
+    $_=shift(@ARGV);
+    if (m/^-p([-+0-9a-z.]+)$/) {
+	$oppackage= $1;
+    } elsif (m/^-c(\d)?$/) {
+	$compare = defined($1) ? $1 : 1;
+    } elsif (m/^-d$/) {
+	$debug = 1;
+    } elsif (m/^-v(.*)/) {
+	$sourceversion = $1;
+    } elsif (m/^-e(.*)/) {
+	my $file = $1;
+	if (-e $file) {
+	    push @files, $file;
+	} else {
+	    push @files, glob($file);
+	}
+    } elsif (m/^-p(.*)/) {
+	&error(sprintf(_g("Illegal package name \`%s'"), $1));
+    } elsif (m/^-P(.*)$/) {
+	$packagebuilddir = $1;
+	$packagebuilddir =~ s{/+$}{};
+    } elsif (m/^-O$/) {
+	$stdout= 1;
+    } elsif (m/^-O(.+)$/) {
+	$output= $1;
+    } elsif (m/^-(h|-help)$/) {
+	&usage; exit(0);
+    } elsif (m/^--version$/) {
+	&version; exit(0);
+    } else {
+	&usageerr(sprintf(_g("unknown option \`%s'"), $_));
+    }
+}
+
+if (not defined($sourceversion)) {
+    parsechangelog($changelogfile);
+    $sourceversion = $fi{"L Version"};
+}
+if (not defined($oppackage)) {
+    parsecontrolfile($controlfile);
+    my @packages = grep(m/^C /, keys %p2i);
+    @packages==1 ||
+	&error(sprintf(_g("must specify package since control info has many (%s)"), "@packages"));
+    $oppackage = $packages[0];
+    $oppackage =~ s/^C //;
+}
+
+my $symfile = Dpkg::Shlibs::SymbolFile->new();
+my $ref_symfile = Dpkg::Shlibs::SymbolFile->new();
+# Load source-provided symbol information
+foreach my $file ($output, "debian/$oppackage.symbols.$host_arch",
+    "debian/symbols.$host_arch", "debian/$oppackage.symbols",
+    "debian/symbols")
+{
+    if (defined $file and -e $file) {
+	print "Using references symbols from $file\n" if $debug;
+	$symfile->load($file);
+	$ref_symfile->load($file) if $compare;
+	last;
+    }
+}
+
+# Scan package build dir looking for libraries
+if (not scalar @files) {
+    foreach my $path (@librarypaths) {
+	my $libdir = "$packagebuilddir$path";
+	$libdir =~ s{/+}{/}g;
+	next if not -d $libdir;
+	opendir(DIR, "$libdir") ||
+	    syserr(sprintf(_g("Can't read directory %s: %s"), $libdir, $!));
+	push @files, grep {
+	    /(\.so\.|\.so$)/ && -f $_ &&
+	    Dpkg::Shlibs::Objdump::is_elf($_);
+	} map { "$libdir/$_" } readdir(DIR);
+	close(DIR);
+    }
+}
+
+# Merge symbol information
+my $od = Dpkg::Shlibs::Objdump->new();
+foreach my $file (@files) {
+    print "Scanning $file for symbol information\n" if $debug;
+    my $objid = $od->parse($file);
+    unless (defined($objid) && $objid) {
+	warning(sprintf(_g("Objdump couldn't parse %s\n"), $file));
+	next;
+    }
+    my $object = $od->get_object($objid);
+    if ($object->{SONAME}) { # Objects without soname are of no interest
+	print "Merging symbols from $file as $object->{SONAME}\n" if $debug;
+	if (not $symfile->has_object($object->{SONAME})) {
+	    $symfile->create_object($object->{SONAME}, "$oppackage #MINVER#");
+	}
+	$symfile->merge_symbols($object, $sourceversion);
+    } else {
+	print "File $file doesn't have a soname. Ignoring.\n" if $debug;
+    }
+}
+$symfile->clear_except(keys %{$od->{objects}});
+
+# Write out symbols files
+if ($stdout) {
+    $output = "standard output";
+    $symfile->save("-");
+} else {
+    unless (defined($output)) {
+	unless($symfile->is_empty()) {
+	    $output = "$packagebuilddir/DEBIAN/symbols";
+	    mkdir("$packagebuilddir/DEBIAN") if not -e "$packagebuilddir/DEBIAN";
+	}
+    }
+    if (defined($output)) {
+	print "Storing symbols in $output.\n" if $debug;
+	$symfile->save($output);
+    } else {
+	print "No symbol information to store.\n" if $debug;
+    }
+}
+
+# Check if generated files differs from reference file
+my $exitcode = 0;
+if ($compare) {
+    use File::Temp;
+    use Digest::MD5;
+    # Compare
+    if ($symfile->has_new_libs($ref_symfile)) {
+	warning(_g("new libraries appeared in the symbols file."));
+	$exitcode = 4 if ($compare >= 4);
+    }
+    if ($symfile->has_lost_libs($ref_symfile)) {
+	warning(_g("some libraries disappeared in the symbols file."));
+	$exitcode = 3 if ($compare >= 3);
+    }
+    if ($symfile->has_new_symbols($ref_symfile)) {
+	warning(_g("some new symbols appeared in the symbols file."));
+	$exitcode = 2 if ($compare >= 2);
+    }
+    if ($symfile->has_lost_symbols($ref_symfile)) {
+	warning(_g("some symbols disappeared in the symbols file."));
+	$exitcode = 1 if ($compare >= 1);
+    }
+    # Output diffs between symbols files if needed
+    my $before = File::Temp->new(TEMPLATE=>'dpkg-gensymbolsXXXXXX');
+    my $after = File::Temp->new(TEMPLATE=>'dpkg-gensymbolsXXXXXX');
+    $ref_symfile->dump($before); $symfile->dump($after);
+    seek($before, 0, 0); seek($after, 0, 0);
+    my ($md5_before, $md5_after) = (Digest::MD5->new(), Digest::MD5->new());
+    $md5_before->addfile($before);
+    $md5_after->addfile($after);
+    if ($md5_before->hexdigest() ne $md5_after->hexdigest()) {
+	if (defined($ref_symfile->{file})) {
+	    warning(sprintf(_g("%s doesn't match completely %s\n"),
+		    $output, $ref_symfile->{file}));
+	} else {
+	    warning(sprintf(_g("no debian/symbols file used as basis for generating %s\n"), $output));
+	}
+	my ($a, $b) = ($before->filename, $after->filename);
+	system("diff", "-u", $a, $b) if -x "/usr/bin/diff";
+    }
+}
+exit($exitcode);

+ 391 - 358
scripts/dpkg-shlibdeps.pl

@@ -1,7 +1,4 @@
-#! /usr/bin/perl
-#
-# dpkg-shlibdeps
-# $Id$
+#!/usr/bin/perl -w
 
 use strict;
 use warnings;
@@ -10,28 +7,281 @@ use English;
 use POSIX qw(:errno_h :signal_h);
 use Dpkg;
 use Dpkg::Gettext;
+use Dpkg::Path qw(relative_to_pkg_root);
+use Dpkg::Version qw(vercmp);
+use Dpkg::Shlibs qw(find_library);
+use Dpkg::Shlibs::Objdump;
+use Dpkg::Shlibs::SymbolFile;
+
+our $host_arch= `dpkg-architecture -qDEB_HOST_ARCH`;
+chomp $host_arch;
+
+# By increasing importance
+my @depfields= qw(Suggests Recommends Depends Pre-Depends);
+my $i=0; my %depstrength = map { $_ => $i++ } @depfields;
+
+push(@INC, $dpkglibdir);
+require 'controllib.pl';
+textdomain("dpkg-dev");
 
 my $shlibsoverride= '/etc/dpkg/shlibs.override';
 my $shlibsdefault= '/etc/dpkg/shlibs.default';
 my $shlibslocal= 'debian/shlibs.local';
-my $shlibsppdir;
-my $shlibsppext= '.shlibs';
-my $varnameprefix= 'shlibs';
+my $packagetype= 'deb';
 my $dependencyfield= 'Depends';
 my $varlistfile= 'debian/substvars';
-my $packagetype= 'deb';
+my $varnameprefix= 'shlibs';
+my $ignore_missing_info= 0;
+my $debug= 0;
+my @exclude = ();
+
+my (@pkg_shlibs, @pkg_symbols);
+if (-d "debian") {
+    push @pkg_symbols, <debian/*/DEBIAN/symbols>;
+    push @pkg_shlibs, <debian/*/DEBIAN/shlibs>;
+}
 
-my @depfields= qw(Suggests Recommends Depends Pre-Depends);
-my %depstrength;
-my $i=0; grep($depstrength{$_}= ++$i, @depfields);
+my ($stdout, %exec);
+foreach (@ARGV) {
+    if (m/^-T(.*)$/) {
+	$varlistfile= $1;
+    } elsif (m/^-p(\w[-:0-9A-Za-z]*)$/) {
+	$varnameprefix= $1;
+    } elsif (m/^-L(.*)$/) {
+	$shlibslocal= $1;
+    } elsif (m/^-O$/) {
+	$stdout= 1;
+    } elsif (m/^-(h|-help)$/) {
+	usage(); exit(0);
+    } elsif (m/^--version$/) {
+	version(); exit(0);
+    } elsif (m/^--admindir=(.*)$/) {
+	$admindir = $1;
+	-d $admindir ||
+	    error(sprintf(_g("administrative directory '%s' does not exist"),
+			  $admindir));
+    } elsif (m/^-d(.*)$/) {
+	$dependencyfield= capit($1);
+	defined($depstrength{$dependencyfield}) ||
+	    warning(sprintf(_g("unrecognised dependency field \`%s'"), $dependencyfield));
+    } elsif (m/^-e(.*)$/) {
+	$exec{$1} = $dependencyfield;
+    } elsif (m/^--ignore-missing-info$/) {
+	$ignore_missing_info = 1;
+    } elsif (m/^-t(.*)$/) {
+	$packagetype = $1;
+    } elsif (m/^-v$/) {
+	$debug = 1;
+    } elsif (m/^-x(.*)$/) {
+	push @exclude, $1;
+    } elsif (m/^-/) {
+	usageerr(sprintf(_g("unknown option \`%s'"), $_));
+    } else {
+	$exec{$_} = $dependencyfield;
+    }
+}
 
-push(@INC,$dpkglibdir);
-require 'controllib.pl';
+scalar keys %exec || usageerr(_g("need at least one executable"));
 
-textdomain("dpkg-dev");
+my %dependencies;
+my %shlibs;
+
+my $cur_field;
+foreach my $file (keys %exec) {
+    $cur_field = $exec{$file};
+    print "Scanning $file (for $cur_field field)\n" if $debug;
 
-#use strict;
-#use warnings;
+    my $obj = Dpkg::Shlibs::Objdump::Object->new($file);
+    my @sonames = $obj->get_needed_libraries;
+
+    # Load symbols files for all needed libraries (identified by SONAME)
+    my %libfiles;
+    foreach my $soname (@sonames) {
+	my $lib = my_find_library($soname, $obj->{RPATH}, $obj->{format}, $file);
+	failure(sprintf(_g("couldn't find library %s (note: only packages with 'shlibs' files are looked into)."), $soname)) unless defined($lib);
+	$libfiles{$lib} = $soname if defined($lib);
+    }
+    my $file2pkg = find_packages(keys %libfiles);
+    my $symfile = Dpkg::Shlibs::SymbolFile->new();
+    my $dumplibs_wo_symfile = Dpkg::Shlibs::Objdump->new();
+    my @soname_wo_symfile;
+    foreach my $lib (keys %libfiles) {
+	my $soname = $libfiles{$lib};
+	if (not exists $file2pkg->{$lib}) {
+	    # If the library is not available in an installed package,
+	    # it's because it's in the process of being built
+	    # Empty package name will lead to consideration of symbols
+	    # file from the package being built only
+	    $file2pkg->{$lib} = [""];
+	}
+
+	# Load symbols/shlibs files from packages providing libraries
+	foreach my $pkg (@{$file2pkg->{$lib}}) {
+	    my $dpkg_symfile;
+	    if ($packagetype eq "deb") {
+		# Use fine-grained dependencies only on real deb
+		$dpkg_symfile = find_symbols_file($pkg, $soname);
+		if (defined $dpkg_symfile) {
+		    # Load symbol information
+		    print "Using symbols file $dpkg_symfile for $soname\n" if $debug;
+		    $symfile->load($dpkg_symfile);
+		}
+	    }
+	    if (defined($dpkg_symfile) && $symfile->has_object($soname)) {
+		# Initialize dependencies as an unversioned dependency
+		my $dep = $symfile->get_dependency($soname);
+		foreach my $subdep (split /\s*,\s*/, $dep) {
+		    if (not exists $dependencies{$cur_field}{$subdep}) {
+			$dependencies{$cur_field}{$subdep} = '';
+		    }
+		}
+	    } else {
+		# No symbol file found, fall back to standard shlibs
+		my $id = $dumplibs_wo_symfile->parse($lib);
+		push @soname_wo_symfile, $soname;
+		my $libobj = $dumplibs_wo_symfile->get_object($id);
+		# Only try to generate a dependency for libraries with a SONAME
+		if ($libobj->is_public_library() and not add_shlibs_dep($soname, $pkg)) {
+		    failure(sprintf(
+			_g("No dependency information found for %s (used by %s)."),
+			$soname, $file)) unless $ignore_missing_info;
+		}
+	    }
+	}
+    }
+
+    # Scan all undefined symbols of the binary and resolve to a
+    # dependency
+    my %used_sonames = map { $_ => 0 } @sonames;
+    foreach my $sym ($obj->get_undefined_dynamic_symbols()) {
+	my $name = $sym->{name};
+	if ($sym->{version}) {
+	    $name .= "\@$sym->{version}";
+	} else {
+	    $name .= "\@Base";
+	}
+	my $symdep = $symfile->lookup_symbol($name, \@sonames);
+	if (defined($symdep)) {
+	    my ($d, $m) = ($symdep->{depends}, $symdep->{minver});
+	    $used_sonames{$symdep->{soname}}++;
+	    foreach my $subdep (split /\s*,\s*/, $d) {
+		if (exists $dependencies{$cur_field}{$subdep} and
+		    defined($dependencies{$cur_field}{$subdep}))
+		{
+		    if ($dependencies{$cur_field}{$subdep} eq '' or
+			vercmp($m, $dependencies{$cur_field}{$subdep}) > 0)
+		    {
+			$dependencies{$cur_field}{$subdep} = $m;
+		    }
+		} else {
+		    $dependencies{$cur_field}{$subdep} = $m;
+		}
+	    }
+	} else {
+	    my $syminfo = $dumplibs_wo_symfile->locate_symbol($name);
+	    if (not defined($syminfo)) {
+		# Complain about missing symbols only for executables
+		# and public libraries
+		if ($obj->is_executable() or $obj->is_public_library()) {
+		    my $print_name = $name;
+		    # Drop the default suffix for readability
+		    $print_name =~ s/\@Base$//;
+		    warning(sprintf(
+			_g("symbol %s used by %s found in none of the libraries."),
+			$print_name, $file)) unless $sym->{weak};
+		}
+	    } else {
+		$used_sonames{$syminfo->{soname}}++;
+	    }
+	}
+    }
+    # Warn about un-NEEDED libraries
+    foreach my $soname (@sonames) {
+	unless ($used_sonames{$soname}) {
+	    warning(sprintf(
+		_g("%s shouldn't be linked with %s (it uses none of its symbols)."),
+		$file, $soname));
+	}
+    }
+}
+
+# Open substvars file
+my $fh;
+if ($stdout) {
+    $fh = \*STDOUT;
+} else {
+    open(NEW, ">", "$varlistfile.new") ||
+	syserr(sprintf(_g("open new substvars file \`%s'"), "$varlistfile.new"));
+    if (-e $varlistfile) {
+	open(OLD, "<", $varlistfile) ||
+	    syserr(sprintf(_g("open old varlist file \`%s' for reading"), $varlistfile));
+	foreach my $entry (grep { not m/^\Q$varnameprefix\E:/ } (<OLD>)) {
+	    print(NEW $entry) ||
+		syserr(sprintf(_g("copy old entry to new varlist file \`%s'"), "$varlistfile.new"));
+	}
+	close(OLD);
+    }
+    $fh = \*NEW;
+}
+
+# Write out the shlibs substvars
+my %depseen;
+
+sub filter_deps {
+    my ($dep, $field) = @_;
+    # Skip dependencies on excluded packages
+    foreach my $exc (@exclude) {
+	return 0 if $dep =~ /^\s*\Q$exc\E\b/;
+    }
+    # Don't include dependencies if they are already
+    # mentionned in a higher priority field
+    if (not defined($depseen{$dep})) {
+	$depseen{$dep} = $dependencies{$field}{$dep};
+	return 1;
+    } else {
+	# Since dependencies can be versionned, we have to
+	# verify if the dependency is stronger than the
+	# previously seen one
+	if (vercmp($depseen{$dep}, $dependencies{$field}{$dep}) > 0) {
+	    return 0;
+	} else {
+	    $depseen{$dep} = $dependencies{$field}{$dep};
+	    return 1;
+	}
+    }
+}
+
+foreach my $field (reverse @depfields) {
+    my $dep = "";
+    if (exists $dependencies{$field} and scalar keys %{$dependencies{$field}}) {
+	$dep = join ", ",
+	    map {
+		# Translate dependency templates into real dependencies
+		if ($dependencies{$field}{$_}) {
+		    s/#MINVER#/(>= $dependencies{$field}{$_})/g;
+		} else {
+		    s/#MINVER#//g;
+		}
+		s/\s+/ /g;
+		$_;
+	    } grep { filter_deps($_, $field) }
+	    keys %{$dependencies{$field}};
+    }
+    if ($dep) {
+	print $fh "$varnameprefix:$field=$dep\n";
+    }
+}
+
+# Replace old file by new one
+if (!$stdout) {
+    close($fh);
+    rename("$varlistfile.new",$varlistfile) ||
+	syserr(sprintf(_g("install new varlist file \`%s'"), $varlistfile));
+}
+
+##
+## Functions
+##
 
 sub version {
     printf _g("Debian %s version %s.\n"), $progname, $version;
@@ -39,7 +289,9 @@ sub version {
     printf _g("
 Copyright (C) 1996 Ian Jackson.
 Copyright (C) 2000 Wichert Akkerman.
-Copyright (C) 2006 Frank Lichtenheld.");
+Copyright (C) 2006 Frank Lichtenheld.
+Copyright (C) 2007 Raphael Hertzog.
+");
 
     printf _g("
 This is free software; see the GNU General Public Licence version 2 or
@@ -62,6 +314,7 @@ Options:
   -L<localshlibsfile>      shlibs override file, not debian/shlibs.local.
   -T<varlistfile>          update variables here, not debian/substvars.
   -t<type>                 set package type (default is deb).
+  -x<package>              exclude package from the generated dependencies.
   --admindir=<directory>   change the administrative directory.
   -h, --help               show this help message.
       --version            show the version.
@@ -71,376 +324,156 @@ Dependency fields recognised are:
 "), $progname, join("/",@depfields);
 }
 
-my ($stdout, @exec, @execfield);
-foreach (@ARGV) {
-    if (m/^-T/) {
-	$varlistfile= $POSTMATCH;
-    } elsif (m/^-p(\w[-:0-9A-Za-z]*)$/) {
-	$varnameprefix= $1;
-    } elsif (m/^-L/) {
-	$shlibslocal= $POSTMATCH;
-    } elsif (m/^-O$/) {
-	$stdout= 1;
-    } elsif (m/^-(h|-help)$/) {
-	usage; exit(0);
-    } elsif (m/^--version$/) {
-	version; exit(0);
-    } elsif (m/^--admindir=/) {
-	$admindir = $POSTMATCH;
-	-d $admindir ||
-	    error(sprintf(_g("administrative directory '%s' does not exist"),
-			     $admindir));
-    } elsif (m/^-d/) {
-	$dependencyfield= capit($POSTMATCH);
-	defined($depstrength{$dependencyfield}) ||
-	    warning(sprintf(_g("unrecognised dependency field '%s'"), $dependencyfield));
-    } elsif (m/^-e/) {
-	push(@exec,$POSTMATCH); push(@execfield,$dependencyfield);
-    } elsif (m/^-t/) {
-	$packagetype= $POSTMATCH;
-    } elsif (m/^-/) {
-	usageerr(sprintf(_g("unknown option \`%s'"), $_));
-    } else {
-	push(@exec,$_); push(@execfield,$dependencyfield);
+sub add_shlibs_dep {
+    my ($soname, $pkg) = @_;
+    foreach my $file ($shlibslocal, $shlibsoverride, @pkg_shlibs,
+			"$admindir/info/$pkg.shlibs",
+			$shlibsdefault)
+    {
+	next if not -e $file;
+	my $dep = extract_from_shlibs($soname, $file);
+	if (defined($dep)) {
+	    foreach (split(/,\s*/, $dep)) {
+		$dependencies{$cur_field}{$_} = 1;
+	    }
+	    return 1;
+	}
     }
+    return 0;
 }
 
-$shlibsppdir = "$admindir/info";
-
-@exec || usageerr(_g("need at least one executable"));
-
-sub isbin {
-    open (F, $_[0]) || die(sprintf(_g("unable to open '%s' for test"), $_[0]));
-    my $d;
-    if (read (F, $d, 4) != 4) {
-       die (sprintf(_g("unable to read first four bytes of '%s' as magic number"), $_[0]));
-    }
-    if ($d =~ /^\177ELF$/) { # ELF binary
-       return 1;
-    } elsif (unpack ('N', $d) == 0x8086010B) { # obsd dyn bin
-       return 1;
-    } elsif (unpack ('N', $d) ==   0x86010B) { # obsd stat bin
-       return 1;
-    } elsif ($d =~ /^\#\!..$/) { # shell script
-       return 0;
-    } elsif (unpack ('N', $d) == 0xcafebabe) { # JAVA binary
-       return 0;
+sub extract_from_shlibs {
+    my ($soname, $shlibfile) = @_;
+    my ($libname, $libversion);
+    # Split soname in name/version
+    if ($soname =~ /^(.*)\.so\.(.*)$/) {
+	$libname = $1; $libversion = $2;
+    } elsif ($soname =~ /^(.*)-(.*)\.so$/) {
+	$libname = $1; $libversion = $2;
     } else {
-       die(sprintf(_g("unrecognized file type for '%s'"), $_[0]));
+	warning(sprintf(_g("Can't extract name and version from library name \`%s'"), $soname));
+	return;
     }
-}
-
-my @librarypaths = qw( /lib /usr/lib /lib32 /usr/lib32 /lib64 /usr/lib64
-		       /emul/ia32-linux/lib /emul/ia32-linux/usr/lib );
-my %librarypaths = map { $_ => 'default' } @librarypaths;
-
-if ($ENV{LD_LIBRARY_PATH}) {
-    foreach (reverse split( /:/, $ENV{LD_LIBRARY_PATH} )) {
-	s,/+$,,;
-	unless (exists $librarypaths{$_}) {
-	    $librarypaths{$_} = 'env';
-	    unshift @librarypaths, $_;
+    # Open shlibs file
+    $shlibfile = "./$shlibfile" if $shlibfile =~ m/^\s/;
+    open(SHLIBS, "<", $shlibfile)
+	|| syserr(sprintf(_g("unable to open shared libs info file \`%s'"), $shlibfile));
+    my $dep;
+    while (<SHLIBS>) {
+	s/\s*\n$//;
+	next if m/^\#/;
+	if (!m/^\s*(?:(\S+):\s+)?(\S+)\s+(\S+)\s+(\S.*\S)\s*$/) {
+	    warning(sprintf(_g("shared libs info file \`%s' line %d: bad line \`%s'"), $shlibfile, $., $_));
+	    next;
 	}
-    }
-}
-
-# Support system library directories.
-my $ldconfigdir = '/lib/ldconfig';
-if (opendir(DIR, $ldconfigdir)) {
-    my @dirents = readdir(DIR);
-    closedir(DIR);
-
-    for (@dirents) {
-	next if /^\./;
-	my $d = `readlink -f $ldconfigdir/$_`;
-	chomp $d;
-	unless (exists $librarypaths{$d}) {
-	    $librarypaths{$d} = 'ldconfig';
-	    push @librarypaths, $d;
+	if (($libname eq $2) && ($libversion eq $3)) {
+	    # Define dep and end here if the package type explicitely
+	    # matches. Otherwise if the packagetype is not specified, use
+	    # the dep only as a default that can be overriden by a later
+	    # line
+	    if (defined($1)) {
+		if ($1 eq $packagetype) {
+		    $dep = $4;
+		    last;
+		}
+	    } else {
+		$dep = $4 unless defined $dep;
+	    }
 	}
     }
+    close(SHLIBS);
+    return $dep;
 }
 
-open CONF, '</etc/ld.so.conf' or
-    warning(sprintf(_g("couldn't open /etc/ld.so.conf: %s"), $!));
-while( <CONF> ) {
-    next if /^\s*$/;
-    chomp;
-    s,/+$,,;
-    unless (exists $librarypaths{$_}) {
-	$librarypaths{$_} = 'conf';
-	push @librarypaths, $_;
-    }
-}
-close CONF;
-
-my (%rpaths, %format);
-my (@libfiles, @libname, @libsoname, @libfield, @libexec);
-for ($i=0;$i<=$#exec;$i++) {
-    if (!isbin ($exec[$i])) { next; }
-
-    # Now we get the direct deps of the program
-    defined(my $c= open(P,"-|")) || syserr(_g("cannot fork for objdump"));
-    if (!$c) {
-	exec("objdump", "-p", "--", $exec[$i]) or
-	    syserr(_g("cannot exec objdump"));
-    }
-    while (<P>) {
-	chomp;
-	if (/^\s*\S+:\s*file\s+format\s+(\S+)\s*$/) {
-	    $format{$exec[$i]} = $1;
-	} elsif (m,^\s*NEEDED\s+,) {
-	    if (m,^\s*NEEDED\s+((\S+)\.so\.(\S+))$,) {
-		push(@libname,$2); push(@libsoname,$3);
-		push(@libfield,$execfield[$i]);
-		push(@libfiles,$1);
-		push(@libexec,$exec[$i]);
-	    } elsif (m,^\s*NEEDED\s+((\S+)-(\S+)\.so)$,) {
-		push(@libname,$2); push(@libsoname,$3);
-		push(@libfield,$execfield[$i]);
-		push(@libfiles,$1);
-		push(@libexec,$exec[$i]);
-	    } else {
-		m,^\s*NEEDED\s+(\S+)$,;
-		warning(sprintf(_g("format of 'NEEDED %s' not recognized"), $1));
-	    }
-	} elsif (/^\s*RPATH\s+(\S+)\s*$/) {
-	    push @{$rpaths{$exec[$i]}}, split(/:/, $1);
+sub find_symbols_file {
+    my ($pkg, $soname) = @_;
+    foreach my $file (@pkg_symbols,
+	"/etc/dpkg/symbols/$pkg.symbols.$host_arch",
+	"/etc/dpkg/symbols/$pkg.symbols",
+	"$admindir/info/$pkg.symbols")
+    {
+	if (-e $file and symfile_has_soname($file, $soname)) {
+	    return $file;
 	}
     }
-    close(P) or subprocerr(sprintf(_g("objdump on \`%s'"), $exec[$i]));
+    return undef;
 }
 
-# Now: See if it is in this package.  See if it is in any other package.
-my @curshlibs;
-sub searchdir {
-    my $dir = shift;
-    if(opendir(DIR, $dir)) {
-	my @dirents = readdir(DIR);
-	closedir(DIR);
-	for (@dirents) {
-	    if ( -f "$dir/$_/DEBIAN/shlibs" ) {
-		push(@curshlibs, "$dir/$_/DEBIAN/shlibs");
-		next;
-	    } elsif ( $_ !~ /^\./ && ! -e "$dir/$_/DEBIAN" &&
-		      -d "$dir/$_" && ! -l "$dir/$_" ) {
-		&searchdir("$dir/$_");
-	    }
+sub symfile_has_soname {
+    my ($file, $soname) = @_;
+    open(SYM_FILE, "<", $file)
+	|| syserr(sprintf(_g("cannot open file %s"), $file));
+    my $result = 0;
+    while (<SYM_FILE>) {
+	if (/^\Q$soname\E /) {
+	    $result = 1;
+	    last;
 	}
     }
+    close(SYM_FILE);
+    return $result;
 }
 
-my $searchdir = $exec[0];
-my $curpackdir = "debian/tmp";
-do { $searchdir =~ s,/[^/]*$,,; } while($searchdir =~ m,/,
-					&& ! -d "$searchdir/DEBIAN");
-if ($searchdir =~ m,/,) {
-    $curpackdir = $searchdir;
-    $searchdir =~ s,/[^/]*,,;
-    &searchdir($searchdir);
-}
+# find_library ($soname, \@rpath, $format)
+sub my_find_library {
+    my ($lib, $rpath, $format, $execfile) = @_;
+    my $file;
+
+    # Create real RPATH in case $ORIGIN is used
+    # Note: ld.so also supports $PLATFORM and $LIB but they are
+    # used in real case (yet)
+    my $origin = "/" . relative_to_pkg_root($execfile);
+    $origin =~ s{/+[^/]*$}{};
+    my @RPATH = ();
+    foreach my $path (@{$rpath}) {
+	$path =~ s/\$ORIGIN/$origin/g;
+	$path =~ s/\$\{ORIGIN\}/$origin/g;
+	push @RPATH, $path;
+    }
 
-if (1 || $#curshlibs >= 0) {
-  PRELIB:
-    for ($i=0;$i<=$#libname;$i++) {
-	if(scanshlibsfile($shlibslocal,$libname[$i],$libsoname[$i],$libfield[$i])
-	   || scanshlibsfile($shlibsoverride,$libname[$i],$libsoname[$i],$libfield[$i])) {
-	    splice(@libname, $i, 1);
-	    splice(@libsoname, $i, 1);
-	    splice(@libfield, $i, 1);
-	    splice(@libfiles, $i, 1);
-	    splice(@libexec, $i, 1);
-	    $i--;
-	    next PRELIB;
-	}
-	for my $shlibsfile (@curshlibs) {
-	    if(scanshlibsfile($shlibsfile, $libname[$i], $libsoname[$i], $libfield[$i])) {
-		splice(@libname, $i, 1);
-		splice(@libsoname, $i, 1);
-		splice(@libfield, $i, 1);
-		splice(@libfiles, $i, 1);
-		splice(@libexec, $i, 1);
-		$i--;
-		next PRELIB;
-	    }
-	}
+    # Look into the packages we're currently building (but only those
+    # that provides shlibs file...)
+    # TODO: we should probably replace that by a cleaner way to look into
+    # the various temporary build directories...
+    foreach my $builddir (map { s{/DEBIAN/shlibs$}{}; $_ } @pkg_shlibs) {
+	$file = find_library($lib, \@RPATH, $format, $builddir);
+	return $file if defined($file);
     }
-}
 
-my %pathpackages;
-if ($#libfiles >= 0) {
-    grep(s/\[\?\*/\\$&/g, @libname);
-    defined(my $c= open(P,"-|")) || syserr(_g("cannot fork for dpkg --search"));
-    if (!$c) {
-	my %seen_libfiles;
-	my @uniq_libfiles = grep !$seen_libfiles{$_}++, @libfiles;
+    # Fallback in the root directory if we have not found what we were
+    # looking for in the packages
+    $file = find_library($lib, \@RPATH, $format, "");
+    return $file if defined($file);
+
+    return undef;
+}
 
-	close STDERR; # we don't need to see dpkg's errors
-	open STDERR, "> /dev/null";
+sub find_packages {
+    my @files = (@_);
+    my $pkgmatch = {};
+    my $pid = open(DPKG, "-|");
+    syserr(_g("cannot fork for dpkg --search")) unless defined($pid);
+    if (!$pid) {
+	# Child process running dpkg --search and discarding errors
+	close STDERR;
+	open STDERR, ">", "/dev/null";
 	$ENV{LC_ALL} = "C";
-	exec("dpkg", "--search", "--", @uniq_libfiles) or
-	    syserr(_g("cannot exec dpkg"));
+	exec("dpkg", "--search", "--", @files)
+	    || syserr(_g("cannot exec dpkg"));
     }
-    while (<P>) {
-	chomp;
+    while(defined($_ = <DPKG>)) {
+	chomp($_);
 	if (m/^local diversion |^diversion by/) {
 	    warning(_g("diversions involved - output may be incorrect"));
-	    print(STDERR " $_\n") || syserr(_g("write diversion info to stderr"));
-	} elsif (m=^(\S+(, \S+)*): (\S+)$=) {
-	    push @{$pathpackages{$LAST_PAREN_MATCH}}, split(/, /, $1);
+	    print(STDERR " $_\n")
+		|| syserr(_g("write diversion info to stderr"));
+	} elsif (m/^([^:]+): (\S+)$/) {
+	    $pkgmatch->{$2} = [ split(/, /, $1) ];
 	} else {
 	    warning(sprintf(_g("unknown output from dpkg --search: '%s'"), $_));
 	}
     }
-    close(P);
+    close(DPKG);
+    return $pkgmatch;
 }
 
- LIB:
-    for ($i=0;$i<=$#libname;$i++) {
-	my $file = $libfiles[$i];
-	my @packages;
-	foreach my $rpath (@{$rpaths{$libexec[$i]}}) {
-	    if (exists $pathpackages{"$rpath/$file"}
-		&& format_matches($libexec[$i],"$rpath/$file")) {
-		push @packages, @{$pathpackages{"$rpath/$file"}};
-	    }
-	}
-	foreach my $path (@librarypaths) {
-	    if (exists $pathpackages{"$path/$file"}
-		&& format_matches($libexec[$i],"$path/$file")) {
-		push @packages, @{$pathpackages{"$path/$file"}};
-	    }
-	}
-	if (!@packages) {
-	    warning(sprintf(_g("could not find any packages for %s"), $libfiles[$i]));
-	} else {
-	    for my $p (@packages) {
-		scanshlibsfile("$shlibsppdir/$p$shlibsppext",
-			       $libname[$i],$libsoname[$i],$libfield[$i])
-		    && next LIB;
-	    }
-	}
-	scanshlibsfile($shlibsdefault,$libname[$i],$libsoname[$i],$libfield[$i])
-	    && next;
-	warning(sprintf(_g("unable to find dependency information for ".
-	                   "shared library %s (soname %s, ".
-	                   "path %s, dependency field %s)"),
-	                $libname[$i], $libsoname[$i],
-	                $libfiles[$i], $libfield[$i]));
-    }
-
-sub format_matches {
-    my ($file1, $file2) = @_;
-    my ($format1, $format2) = (get_format($file1),get_format($file2));
-    return $format1 eq $format2;
-}
-
-sub get_format {
-    my ($file) = @_;
-
-    if ($format{$file}) {
-	return $format{$file};
-    } else {
-	defined(my $c= open(P,"-|")) || syserr(_g("cannot fork for objdump"));
-	if (!$c) {
-	    exec("objdump", "-a", "--", $file) or
-		syserr(_g("cannot exec objdump"));
-	}
-	while (<P>) {
-	    chomp;
-	    if (/^\s*\S+:\s*file\s+format\s+(\S+)\s*$/) {
-		$format{$file} = $1;
-		return $format{$file};
-	    }
-	}
-	close(P) or subprocerr(sprintf(_g("objdump on \`%s'"), $file));
-    }
-}
-
-my (%predefdepfdep, %unkdepfdone, %unkdepf);
-sub scanshlibsfile {
-    my ($fn,$ln,$lsn,$lf) = @_;
-    my ($da,$dk);
-    $fn= "./$fn" if $fn =~ m/^\s/;
-    if (!open(SLF,"< $fn")) {
-        $! == ENOENT || syserr(sprintf(_g("unable to open shared libs info file \`%s'"), $fn));
-        return 0;
-    }
-
-    while (<SLF>) {
-        s/\s*\n$//; next if m/^\#/;
-        if (!m/^\s*(?:(\S+):\s+)?(\S+)\s+(\S+)/) {
-	    warning(sprintf(_g("shared libs info file '%s' line %d: bad line '%s'"), $fn, $., $_));
-            next;
-        }
-        next if defined $1 && $1 ne $packagetype;
-        next if $2 ne $ln || $3 ne $lsn;
-        return 1 if $fn eq "$curpackdir/DEBIAN/shlibs";
-        $da= $POSTMATCH;
-        last if defined $1; # exact match, otherwise keep looking
-    }
-    close(SLF);
-
-    return 0 unless defined $da;
-
-    for my $dv (split(/,/,$da)) {
-        $dv =~ s/^\s+//; $dv =~ s/\s+$//;
-        if (defined($depstrength{$lf})) {
-            if (!defined($predefdepfdep{$dv}) ||
-                $depstrength{$predefdepfdep{$dv}} < $depstrength{$lf}) {
-                $predefdepfdep{$dv}= $lf;
-            }
-        } else {
-            $dk= "$lf: $dv";
-            if (!defined($unkdepfdone{$dk})) {
-                $unkdepfdone{$dk}= 1;
-                $unkdepf{$lf} .= ', ' if defined($unkdepf{$lf});
-                $unkdepf{$lf}.= $dv;
-            }
-        }
-    }
-    return 1;
-}
-
-my $fh;
-if (!$stdout) {
-    open(Y,"> $varlistfile.new") ||
-        syserr(sprintf(_g("open new substvars file \`%s'"), "$varlistfile.new"));
-    unless ($REAL_USER_ID) {
-	chown(getfowner(), "$varlistfile.new") ||
-	    syserr(sprintf(_g("chown of \`%s'"), "$varlistfile.new"));
-    }
-    if (open(X,"< $varlistfile")) {
-        while (<X>) {
-            s/\n$//;
-            next if m/^(\w[-:0-9A-Za-z]*):/ && $1 eq $varnameprefix;
-            print(Y "$_\n") ||
-                syserr(sprintf(_g("copy old entry to new varlist file \`%s'"), "$varlistfile.new"));
-        }
-    } elsif ($! != ENOENT) {
-        syserr(sprintf(_g("open old varlist file \`%s' for reading"), $varlistfile));
-    }
-    $fh = \*Y;
-} else {
-    $fh = \*STDOUT;
-}
-my %defdepf;
-for my $dv (sort keys %predefdepfdep) {
-    my $lf= $predefdepfdep{$dv};
-    $defdepf{$lf} .= ', ' if defined($defdepf{$lf});
-    $defdepf{$lf}.= $dv;
-}
-for my $lf (reverse @depfields) {
-    next unless defined($defdepf{$lf});
-    print($fh "$varnameprefix:$lf=$defdepf{$lf}\n")
-        || syserr(_g("write output entry"));
-}
-for my $lf (sort keys %unkdepf) {
-    print($fh "$varnameprefix:$lf=$unkdepf{$lf}\n")
-        || syserr(_g("write userdef output entry"));
-}
-close($fh) || syserr(_g("close output"));
-if (!$stdout) {
-    rename("$varlistfile.new",$varlistfile) ||
-        syserr(sprintf(_g("install new varlist file \`%s'"), $varlistfile));
-}

+ 110 - 59
scripts/dpkg-source.pl

@@ -76,6 +76,15 @@ my $def_dscformat = "1.0"; # default format for -b
 
 my $expectprefix;
 
+# Compression
+my @comp_supported = qw(gzip bzip2 lzma);
+my %comp_supported = map { $_ => 1 } @comp_supported;
+my %comp_ext = ( gzip => 'gz', bzip2 => 'bz2', lzma => 'lzma' );
+my $comp_regex = '(?:gz|bz2|lzma)';
+my $compression = 'gzip';
+my $comp_level = '9';
+my $comp_ext = $comp_ext{$compression};
+
 # Packages
 my %remove;
 my %override;
@@ -91,6 +100,7 @@ my @tar_ignore;
 
 use POSIX;
 use Fcntl qw (:mode);
+use English;
 use File::Temp qw (tempfile);
 use Cwd;
 
@@ -155,8 +165,8 @@ Build options:
   -T<varlistfile>          read variables here, not debian/substvars.
   -D<field>=<value>        override or add a .dsc field and value.
   -U<field>                remove a field.
-  -W                       turn certain errors into warnings.
-  -E                       when -W is enabled, -E disables it.
+  -E                       turn certain warnings into errors.
+  -W                       when -E is enabled, -W disables it.
   -q                       quiet operation, do not print warnings.
   -i[<regexp>]             filter out files to ignore diffs of
                              (defaults to: '%s').
@@ -170,6 +180,10 @@ Build options:
   -ss                      trust packed & unpacked orig src are same.
   -sn                      there is no diff, do main tarfile only.
   -sA,-sK,-sP,-sU,-sR      like -sa,-sk,-sp,-su,-sr but may overwrite.
+  -Z<compression>          select compression to use (defaults to 'gzip',
+                             supported are: %s).
+  -z<level>                compression level to use (defaults to '9',
+                             supported are: '1'-'9', 'best', 'fast')
 
 Extract options:
   -sp (default)            leave orig source packed in current dir.
@@ -181,7 +195,8 @@ General options:
       --version            show the version.
 "), $progname,
     $diff_ignore_default_regexp,
-    join('', map { " -I$_" } @tar_ignore_default_pattern);
+    join('', map { " -I$_" } @tar_ignore_default_pattern),
+    "@comp_supported" ;
 }
 
 sub handleformat {
@@ -207,18 +222,27 @@ while (@ARGV && $ARGV[0] =~ m/^-/) {
         &setopmode('build');
     } elsif (m/^-x$/) {
         &setopmode('extract');
+    } elsif (m/^-Z/) {
+	$compression = $POSTMATCH;
+	$comp_ext = $comp_ext{$compression};
+	usageerr(sprintf(_g("%s is not a supported compression"), $compression))
+	    unless $comp_supported{$compression};
+    } elsif (m/^-z/) {
+	$comp_level = $POSTMATCH;
+	usageerr(sprintf(_g("%s is not a compression level"), $comp_level))
+	    unless $comp_level =~ /^([1-9]|fast|best)$/;
     } elsif (m/^-s([akpursnAKPUR])$/) {
 	warning(sprintf(_g("-s%s option overrides earlier -s%s option"), $1, $sourcestyle))
 	    if $sourcestyle ne 'X';
         $sourcestyle= $1;
     } elsif (m/^-c/) {
-        $controlfile= $';
+        $controlfile= $POSTMATCH;
     } elsif (m/^-l/) {
-        $changelogfile= $';
+        $changelogfile= $POSTMATCH;
     } elsif (m/^-F([0-9a-z]+)$/) {
         $changelogformat=$1;
     } elsif (m/^-D([^\=:]+)[=:]/) {
-        $override{$1}= "$'";
+        $override{$1}= $POSTMATCH;
     } elsif (m/^-U([^\=:]+)$/) {
         $remove{$1}= 1;
     } elsif (m/^-i(.*)$/) {
@@ -233,9 +257,9 @@ while (@ARGV && $ARGV[0] =~ m/^-/) {
             $tar_ignore_default_pattern_done = 1;
         }
     } elsif (m/^-V(\w[-:0-9A-Za-z]*)[=:]/) {
-        $substvar{$1}= "$'";
+        $substvar{$1}= $POSTMATCH;
     } elsif (m/^-T/) {
-        $varlistfile= "$'";
+        $varlistfile= $POSTMATCH;
     } elsif (m/^-(h|-help)$/) {
         &usage; exit(0);
     } elsif (m/^--version$/) {
@@ -271,7 +295,7 @@ if ($opmode eq 'build') {
     
     parsechangelog($changelogfile, $changelogformat);
     parsecontrolfile($controlfile);
-    $f{"Format"}=$def_dscformat;
+    $f{"Format"}= $compression eq 'gzip' ? $def_dscformat : '2.0';
     &init_substvars;
 
     my @sourcearch;
@@ -416,7 +440,7 @@ if ($opmode eq 'build') {
     $basedirname =~ s/_/-/;
 
     my $origdir = "$dir.orig";
-    my $origtargz = "$basename.orig.tar.gz";
+    my $origtargz;
     if (@ARGV) {
         my $origarg = shift(@ARGV);
         if (length($origarg)) {
@@ -427,7 +451,7 @@ if ($opmode eq 'build') {
                 $sourcestyle =~ y/aA/rR/;
                 $sourcestyle =~ m/[ursURS]/ ||
                     &error(sprintf(_g("orig argument is unpacked but source handling style".
-                           " -s%s calls for packed (.orig.tar.gz)"), $sourcestyle));
+                           " -s%s calls for packed (.orig.tar.<ext>)"), $sourcestyle));
             } elsif (-f _) {
                 $origtargz= $origarg;
                 $sourcestyle =~ y/aA/pP/;
@@ -443,22 +467,28 @@ if ($opmode eq 'build') {
                 &error(sprintf(_g("orig argument is empty (means no orig, no diff)".
                        " but source handling style -s%s wants something"), $sourcestyle));
         }
-    }
-
-    if ($sourcestyle =~ m/[aA]/) {
-        if (stat("$origtargz")) {
-            -f _ || &error(sprintf(_g("packed orig `%s' exists but is not a plain file"), $origtargz));
-            $sourcestyle =~ y/aA/pP/;
-        } elsif ($! != ENOENT) {
-            &syserr(sprintf(_g("unable to stat putative packed orig `%s'"), $origtargz));
-        } elsif (stat("$origdir")) {
-            -d _ || &error(sprintf(_g("unpacked orig `%s' exists but is not a directory"), $origdir));
-            $sourcestyle =~ y/aA/rR/;
-        } elsif ($! != ENOENT) {
-            &syserr(sprintf(_g("unable to stat putative unpacked orig `%s'"), $origdir));
-        } else {
-            $sourcestyle =~ y/aA/nn/;
-        }
+    } elsif ($sourcestyle =~ m/[aA]/) {
+	my @origtargz = map { "$basename.orig.tar.$comp_ext{$_}" } ($compression, @comp_supported);
+	foreach my $origtar (@origtargz) {
+	    if (stat($origtar)) {
+		-f _ || &error(sprintf(_g("packed orig `%s' exists but is not a plain file"), $origtar));
+		$sourcestyle =~ y/aA/pP/;
+		$origtargz = $origtar;
+		last;
+	    } elsif ($! != ENOENT) {
+		&syserr(sprintf(_g("unable to stat putative packed orig `%s'"), $origtar));
+	    }
+	}
+	if (!$origtargz) {
+	    if (stat($origdir)) {
+		-d _ || &error(sprintf(_g("unpacked orig `%s' exists but is not a directory"), $origdir));
+		$sourcestyle =~ y/aA/rR/;
+	    } elsif ($! != ENOENT) {
+		&syserr(sprintf(_g("unable to stat putative unpacked orig `%s'"), $origdir));
+	    } else {
+		$sourcestyle =~ y/aA/nn/;
+	    }
+	}
     }
 
     my $dirbase = $dir;
@@ -495,13 +525,14 @@ if ($opmode eq 'build') {
 	                       $origdirname, "$basedirname.orig"));
         $tardirbase= $origdirbase; $tardirname= $origdirname;
 
-        $tarname= $origtargz;
-        $tarname eq "$basename.orig.tar.gz" ||
-	    warning(sprintf(_g(".orig.tar.gz name %s is not <package>_<upstreamversion>" .
-	                       ".orig.tar.gz (wanted %s)"), $tarname, "$basename.orig.tar.gz"));
+	$tarname= $origtargz || "$basename.orig.tar.$comp_ext";
+	$tarname =~ /$basename.orig.tar.($comp_regex)/ ||
+	    warning(sprintf(_g(".orig.tar name %s is not <package>_<upstreamversion>" .
+			       ".orig.tar (wanted %s)"), $tarname, "$basename.orig.tar.$comp_regex"));
+	if (($1 ne 'gz') && ($f{'Format'} < 2)) { $f{'Format'} = '2.0' };
     } else {
-        $tardirbase= $dirbase; $tardirname= $dirname;
-        $tarname= "$basenamerev.tar.gz";
+	$tardirbase= $dirbase; $tardirname= $dirname;
+	$tarname= "$basenamerev.tar.$comp_ext";
     }
 
     if ($sourcestyle =~ m/[nurURv]/) {
@@ -582,11 +613,12 @@ if ($opmode eq 'build') {
     }
         
     if ($sourcestyle =~ m/[kpursKPUR]/) {
-        
+
+	my $diffname = "$basenamerev.diff.$comp_ext";
         printf(_g("%s: building %s in %s")."\n",
-               $progname, $sourcepackage, "$basenamerev.diff.gz")
+               $progname, $sourcepackage, $diffname)
             || &syserr(_g("write building diff message"));
-	my ($ndfh, $newdiffgz) = tempfile( "$basenamerev.diff.gz.new.XXXXXX",
+	my ($ndfh, $newdiffgz) = tempfile( "$diffname.new.XXXXXX",
 					DIR => &getcwd, UNLINK => 0 );
         &forkgzipwrite($newdiffgz);
 
@@ -666,7 +698,7 @@ if ($opmode eq 'build') {
                         s/\n$//;
                         &internerr(sprintf(_g("unknown line from diff -u on %s: `%s'"), $fn, $_));
                     }
-                    print(GZIP $_) || &syserr(_g("failed to write to gzip"));
+		    print(GZIP $_) || &syserr(_g("failed to write to compression pipe"));
                 }
                 close(DIFFGEN); $/= "\0";
 		my $es;
@@ -696,12 +728,12 @@ if ($opmode eq 'build') {
             }
         }
         close(FIND); $? && subprocerr("find on $dir");
-        close(GZIP) || &syserr(_g("finish write to gzip pipe"));
+	close(GZIP) || &syserr(_g("finish write to compression pipe"));
         &reapgzip;
-        rename($newdiffgz,"$basenamerev.diff.gz") ||
-            &syserr(sprintf(_g("unable to rename `%s' (newly created) to `%s'"), $newdiffgz, "$basenamerev.diff.gz"));
-	chmod(0666 &~ umask(), "$basenamerev.diff.gz") ||
-	    &syserr(sprintf(_g("unable to change permission of `%s'"), "$basenamerev.diff.gz"));
+	rename($newdiffgz, $diffname) ||
+	    &syserr(sprintf(_g("unable to rename `%s' (newly created) to `%s'"), $newdiffgz, $diffname));
+	chmod(0666 &~ umask(), $diffname) ||
+	    &syserr(sprintf(_g("unable to change permission of `%s'"), $diffname));
 
         defined($c2= open(FIND,"-|")) || &syserr(_g("fork for 2nd find"));
         if (!$c2) {
@@ -728,7 +760,7 @@ if ($opmode eq 'build') {
         }
         close(FIND); $? && subprocerr("find on $dirname");
 
-        &addfile("$basenamerev.diff.gz");
+	&addfile($diffname);
 
     }
 
@@ -852,7 +884,7 @@ if ($opmode eq 'build') {
 
 	&error(sprintf(_g("Files field contains invalid filename `%s'"), $file))
 	    unless s/^\Q$sourcepackage\E_\Q$baseversion\E(?=[.-])// and
-		   s/\.(gz|bz2|lzma)$//;
+		   s/\.$comp_regex$//;
 	s/^-\Q$revision\E(?=\.)// if length $revision;
 
 	&error(sprintf(_g("repeated file type - files `%s' and `%s'"), $seen{$_}, $file)) if $seen{$_};
@@ -1031,7 +1063,7 @@ if ($opmode eq 'build') {
 
     for my $patch (@patches) {
 	printf(_g("%s: applying %s")."\n", $progname, $patch);
-	if ($patch =~ /\.(gz|bz2|lzma)$/) {
+	if ($patch =~ /\.$comp_regex$/) {
 	    &forkgzipread($patch);
 	    *DIFF = *GZIP;
 	} else {
@@ -1051,7 +1083,7 @@ if ($opmode eq 'build') {
         $c2 == waitpid($c2,0) || &syserr(_g("wait for patch"));
         $? && subprocerr("patch");
 
-	&reapgzip if $patch =~ /\.(gz|bz2|lzma)$/;
+	&reapgzip if $patch =~ /\.$comp_regex$/;
     }
 
     my $now = time;
@@ -1334,7 +1366,7 @@ sub checktarsane {
 sub checkdiff
 {
     my $diff = shift;
-    if ($diff =~ /\.(gz|bz2|lzma)$/) {
+    if ($diff =~ /\.$comp_regex$/) {
 	&forkgzipread($diff);
 	*DIFF = *GZIP;
     } else {
@@ -1410,7 +1442,7 @@ sub checkdiff
     }
     close(DIFF);
     
-    &reapgzip if $diff =~ /\.(gz|bz2|lzma)$/;
+    &reapgzip if $diff =~ /\.$comp_regex$/;
 }
 
 sub extracttar {
@@ -1528,13 +1560,30 @@ my $cgz;
 my $gzipsigpipeok;
 
 sub forkgzipwrite {
-    open(GZIPFILE,"> $_[0]") || &syserr(sprintf(_g("create file %s"), $_[0]));
+    my @prog;
+
+    if ($_[0] =~ /\.gz\.new\..{6}$/) {
+	@prog = qw(gzip);
+    } elsif ($_[0] =~ /\.bz2\.new\..{6}$/) {
+	@prog = qw(bzip2);
+    } elsif ($_[0] =~ /\.lzma\.new\..{6}$/) {
+	@prog = qw(lzma);
+    } else {
+	&error(sprintf(_g("unknown compression type on file %s"), $_[0]));
+    }
+    my $level = "-$comp_level";
+    $level = "--$comp_level"
+	if $comp_level =~ /best|fast/;
+    push @prog, $level;
+
+    open(GZIPFILE,">", $_[0]) || &syserr(sprintf(_g("create file %s"), $_[0]));
     pipe(GZIPREAD,GZIP) || &syserr(_g("pipe for gzip"));
     defined($cgz= fork) || &syserr(_g("fork for gzip"));
     if (!$cgz) {
-        open(STDIN,"<&GZIPREAD") || &syserr(_g("reopen gzip pipe")); close(GZIPREAD);
-        close(GZIP); open(STDOUT,">&GZIPFILE") || &syserr(_g("reopen tar.gz"));
-        exec('gzip','-9') or &syserr(_g("exec gzip"));
+	open(STDIN,"<&",\*GZIPREAD) || &syserr(_g("reopen gzip pipe"));
+	close(GZIPREAD); close(GZIP);
+	open(STDOUT,">&",\*GZIPFILE) || &syserr(_g("reopen tar"));
+	exec({ $prog[0] } @prog) or &syserr(_g("exec gzip"));
     }
     close(GZIPREAD);
     $gzipsigpipeok= 0;
@@ -1554,13 +1603,14 @@ sub forkgzipread {
       &error(sprintf(_g("unknown compression type on file %s"), $_[0]));
     }
 
-    open(GZIPFILE,"< $_[0]") || &syserr(sprintf(_g("read file %s"), $_[0]));
+    open(GZIPFILE,"<", $_[0]) || &syserr(sprintf(_g("read file %s"), $_[0]));
     pipe(GZIP,GZIPWRITE) || &syserr(sprintf(_g("pipe for %s"), $prog));
     defined($cgz= fork) || &syserr(sprintf(_g("fork for %s"), $prog));
     if (!$cgz) {
-        open(STDOUT,">&GZIPWRITE") || &syserr(sprintf(_g("reopen %s pipe"), $prog)); close(GZIPWRITE);
-        close(GZIP); open(STDIN,"<&GZIPFILE") || &syserr(_g("reopen input file"));
-        exec($prog) or &syserr(sprintf(_g("exec %s"), $prog));
+	open(STDOUT,">&",\*GZIPWRITE) || &syserr(sprintf(_g("reopen %s pipe"), $prog));
+	close(GZIPWRITE); close(GZIP);
+	open(STDIN,"<&",\*GZIPFILE) || &syserr(_g("reopen input file"));
+	exec({ $prog } $prog) or &syserr(sprintf(_g("exec %s"), $prog));
     }
     close(GZIPWRITE);
     $gzipsigpipeok= 1;
@@ -1598,9 +1648,10 @@ sub deoctify {
     @_= split(/\\/, $fn);
 
     foreach (@_) {
-        /^(\d{3})/ or next;
-        &failure(sprintf(_g("bogus character `\\%s' in `%s'"), $1, $fn)."\n") if oct($1) > 255;
-        $_= pack("c", oct($1)) . $';
+	/^(\d{3})/ or next;
+	&failure(sprintf(_g("bogus character `\\%s' in `%s'"), $1, $fn)."\n")
+	    if oct($1) > 255;
+	$_= pack("c", oct($1)) . $POSTMATCH;
     }
     return join("", @_);
 } }

+ 4 - 0
scripts/po/ChangeLog

@@ -1,3 +1,7 @@
+2007-10-08 Robert Luberda <robert@debian.org>
+
+	* LINGUAS, pl.po: Initial Polish translation with 322t69f71u.
+
 2007-09-28  Peter Karlsson  <peterk@debian.org>
 
 	* sv.po: Updated Swedish to 462t.

+ 3 - 0
scripts/po/LINGUAS

@@ -10,5 +10,8 @@ ca
 # French - Philippe Batailler <philippe.batailler@free.fr>
 fr
 
+# Polish - Robert Luberda <robert@debian.org>
+pl
+
 # Swedish - Peter Karlsson <peterk@debian.org>
 sv

+ 6 - 1
scripts/po/POTFILES.in

@@ -8,10 +8,15 @@ scripts/dpkg-checkbuilddeps.pl
 scripts/dpkg-distaddfile.pl
 scripts/dpkg-genchanges.pl
 scripts/dpkg-gencontrol.pl
+scripts/dpkg-gensymbols.pl
 scripts/dpkg-parsechangelog.pl
 scripts/dpkg-scanpackages.pl
 scripts/dpkg-scansources.pl
 scripts/dpkg-shlibdeps.pl
 scripts/dpkg-source.pl
 scripts/changelog/debian.pl
-
+scripts/Dpkg/Shlibs.pm
+scripts/Dpkg/Shlibs/Objdump.pm
+scripts/Dpkg/Shlibs/SymbolFile.pm
+scripts/Dpkg/Version.pm
+scripts/Dpkg/ErrorHandling.pm

File diff suppressed because it is too large
+ 2593 - 0
scripts/po/pl.po


+ 11 - 0
scripts/t/000_pod.t

@@ -0,0 +1,11 @@
+# -*- mode: cperl;-*-
+
+use Test::More;
+
+use strict;
+use warnings;
+
+eval "use Test::Pod 1.00";
+plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
+my @poddirs = ( $ENV{srcdir} || '.' );
+all_pod_files_ok( all_pod_files( @poddirs ) );

+ 80 - 0
scripts/t/100_Dpkg_Version.t

@@ -0,0 +1,80 @@
+# -*- mode: cperl;-*-
+
+use Test::More;
+
+use warnings;
+use strict;
+
+# Default cmp '>'
+my @versions = ({a      => '1.0-1',
+		 b      => '2.0-2',
+		 result => -1,
+		 relation => 'lt',
+		},
+		{a      => '2.2~rc-4',
+		 b      => '2.2-1',
+		 result => -1,
+		 relation => 'lt',
+		},
+		{a      => '2.2-1',
+		 b      => '2.2~rc-4',
+		 result => 1,
+		 relation => 'gt',
+		},
+		{a      => '1.0000-1',
+		 b      => '1.0-1',
+		 result => 0,
+		 relation => 'eq',
+		},
+		{a      => '1.0000-1',
+		 b      => '1.0-1',
+		 result => 0,
+		 relation => 'ge',
+		},
+		{a      => '1',
+		 b      => '0:1',
+		 result => 0,
+		 relation => 'eq',
+		},
+		{a      => '2:2.5',
+		 b      => '1:7.5',
+		 result => 1,
+		 relation => 'gt',
+		},
+	       );
+my @test_failure = ({a      => '1.0-1',
+		     b      => '2.0-2',
+		     relation => 'gt',
+		    },
+		    {a      => '2.2~rc-4',
+		     b      => '2.2-1',
+		     relation => 'eq',
+		    },
+		   );
+
+plan tests => @versions * 3 + @test_failure * 2 + 1;
+
+sub dpkg_vercmp{
+     my ($a,$b,$cmp) = @_;
+     $cmp = 'gt' if not defined $cmp;
+     return system('dpkg','--compare-versions',$a,$cmp,$b) == 0;
+}
+
+
+use_ok('Dpkg::Version');
+
+for my $version_cmp (@versions) {
+     ok(Dpkg::Version::vercmp($$version_cmp{a},$$version_cmp{b}) == $$version_cmp{result},
+	"vercmp: Version $$version_cmp{a} $$version_cmp{relation} $$version_cmp{b} ok");
+     ok(Dpkg::Version::compare_versions($$version_cmp{a},$$version_cmp{relation},$$version_cmp{b}),
+       "compare_versions: Version $$version_cmp{a} $$version_cmp{relation} $$version_cmp{b} ok");
+     ok(dpkg_vercmp($$version_cmp{a},$$version_cmp{b},$$version_cmp{relation}),
+	"Dpkg concures: Version $$version_cmp{a} $$version_cmp{relation} $$version_cmp{b}");
+}
+
+for my $version_cmp (@test_failure) {
+     ok(!Dpkg::Version::compare_versions($$version_cmp{a},$$version_cmp{relation},$$version_cmp{b}),
+       "compare_versions: Version $$version_cmp{a} $$version_cmp{relation} $$version_cmp{b} false");
+     ok(!dpkg_vercmp($$version_cmp{a},$$version_cmp{b},$$version_cmp{relation}),
+	"Dpkg concures: Version $$version_cmp{a} $$version_cmp{relation} $$version_cmp{b}");
+}

+ 148 - 0
scripts/t/200_Dpkg_Shlibs.t

@@ -0,0 +1,148 @@
+# -*- mode: cperl;-*-
+
+use Test::More tests => 27;
+
+use strict;
+use warnings;
+
+use_ok('Dpkg::Shlibs');
+
+my @save_paths = @Dpkg::Shlibs::librarypaths;
+@Dpkg::Shlibs::librarypaths = ();
+
+my $srcdir = $ENV{srcdir} || '.';
+$srcdir .= '/t/200_Dpkg_Shlibs';
+
+Dpkg::Shlibs::parse_ldso_conf("t.tmp/ld.so.conf");
+
+use Data::Dumper;
+is_deeply([qw(/nonexistant32 /nonexistant/lib64
+	     /usr/local/lib /nonexistant/lib128 )],
+	  \@Dpkg::Shlibs::librarypaths, "parsed library paths");
+
+use_ok('Dpkg::Shlibs::Objdump');
+
+my $obj = Dpkg::Shlibs::Objdump::Object->new;
+
+open my $objdump, '<', "$srcdir/objdump.libc6-2.6"
+  or die "$srcdir/objdump.libc6-2.6: $!";
+$obj->_parse($objdump);
+close $objdump;
+
+is($obj->{SONAME}, 'libc.so.6', 'SONAME');
+is($obj->{HASH}, '0x13d99c', 'HASH');
+is($obj->{GNU_HASH}, '0x194', 'GNU_HASH');
+is($obj->{format}, 'elf32-i386', 'format');
+is_deeply($obj->{flags}, { DYNAMIC => 1, HAS_SYMS => 1, D_PAGED => 1 }, 'flags');
+is_deeply($obj->{NEEDED}, [ 'ld-linux.so.2' ], 'NEEDED');
+is_deeply([ $obj->get_needed_libraries ], [ 'ld-linux.so.2' ], 'NEEDED');
+
+my $sym = $obj->get_symbol('_sys_nerr@GLIBC_2.3');
+is_deeply( $sym, { name => '_sys_nerr', version => 'GLIBC_2.3',
+		   soname => 'libc.so.6', section => '.rodata', dynamic => 1,
+		   debug => '', type => 'O', weak => '',
+		   local => '', global => 1, visibility => '',
+		   hidden => 1, defined => 1 }, 'Symbol' );
+$sym = $obj->get_symbol('_IO_stdin_used');
+is_deeply( $sym, { name => '_IO_stdin_used', version => '',
+		   soname => 'libc.so.6', section => '*UND*', dynamic => 1,
+		   debug => '', type => ' ', weak => 1,
+		   local => '', global => '', visibility => '',   
+		   hidden => '', defined => '' }, 'Symbol 2' );
+
+my @syms = $obj->get_exported_dynamic_symbols;
+is( scalar @syms, 2231, 'defined && dynamic' );
+@syms = $obj->get_undefined_dynamic_symbols;
+is( scalar @syms, 9, 'undefined && dynamic' );
+
+
+my $obj_old = Dpkg::Shlibs::Objdump::Object->new;
+
+open $objdump, '<', "$srcdir/objdump.libc6-2.3"
+  or die "$srcdir/objdump.libc6-2.3: $!";
+$obj_old->_parse($objdump);
+close $objdump;
+
+
+use_ok('Dpkg::Shlibs::SymbolFile');
+
+my $sym_file = Dpkg::Shlibs::SymbolFile->new("$srcdir/symbol_file.tmp");
+my $sym_file_dup = Dpkg::Shlibs::SymbolFile->new("$srcdir/symbol_file.tmp");
+my $sym_file_old = Dpkg::Shlibs::SymbolFile->new("$srcdir/symbol_file.tmp");
+
+$sym_file->merge_symbols($obj_old, "2.3.6.ds1-13");
+$sym_file_old->merge_symbols($obj_old, "2.3.6.ds1-13");
+
+ok( $sym_file->has_object('libc.so.6'), 'SONAME in sym file' );
+
+$sym_file->merge_symbols($obj, "2.6-1");
+
+ok( $sym_file->has_new_symbols($sym_file_old), 'has new symbols' );
+ok( $sym_file_old->has_lost_symbols($sym_file), 'has lost symbols' );
+
+is( $sym_file_old->lookup_symbol('__bss_start@Base', ['libc.so.6']),
+    undef, 'internal symbols are blacklisted');
+
+$sym = $sym_file->lookup_symbol('_errno@GLIBC_2.0', ['libc.so.6'], 1);
+is_deeply($sym, { 'minver' => '2.3.6.ds1-13', 'dep_id' => 0, 
+		  'deprecated' => '2.6-1', 'depends' => '', 
+		  'soname' => 'libc.so.6' }, 'deprecated symbol');
+
+use File::Temp;
+
+my $save_file = new File::Temp;
+
+$sym_file->save($save_file->filename);
+
+$sym_file_dup->load($save_file->filename);
+$sym_file_dup->{file} = "$srcdir/symbol_file.tmp";
+
+is_deeply($sym_file_dup, $sym_file, 'save -> load' );
+
+# Test include mechanism of SymbolFile
+$sym_file = Dpkg::Shlibs::SymbolFile->new("$srcdir/symbols.include-1");
+
+$sym = $sym_file->lookup_symbol('symbol_before@Base', ['libfake.so.1']);
+is_deeply($sym, { 'minver' => '0.9', 'dep_id' => 0, 'deprecated' => 0,
+		  'depends' => 'libfake1 #MINVER#', 'soname' => 'libfake.so.1' }, 
+	    'symbol before include not lost');
+
+$sym = $sym_file->lookup_symbol('symbol_after@Base', ['libfake.so.1']);
+is_deeply($sym, {'minver' => '1.1', 'dep_id' => 0, 'deprecated' => 0, 
+		  'depends' => 'libfake1 #MINVER#', 'soname' => 'libfake.so.1' }, 
+	    'symbol after include not lost');
+
+$sym = $sym_file->lookup_symbol('symbol1_fake1@Base', ['libfake.so.1']);
+is_deeply($sym, {'minver' => '1.0', 'dep_id' => 0, 'deprecated' => 0, 
+		  'depends' => 'libfake1 #MINVER#', 'soname' => 'libfake.so.1' }, 
+	    'overrides order with #include');
+
+$sym = $sym_file->lookup_symbol('symbol3_fake1@Base', ['libfake.so.1']);
+is_deeply($sym, { 'minver' => '1.1', 'dep_id' => 0, 'deprecated' => 0,
+		  'depends' => 'libfake1 #MINVER#', 'soname' => 'libfake.so.1' }, 
+	    'overrides order with #include');
+
+$sym_file = Dpkg::Shlibs::SymbolFile->new("$srcdir/symbols.include-2");
+
+$sym = $sym_file->lookup_symbol('symbol1_fake2@Base', ['libfake.so.1']);
+is_deeply($sym, { 'minver' => '1.0', 'dep_id' => 1, 'deprecated' => 0,
+		  'depends' => 'libvirtualfake', 'soname' => 'libfake.so.1' }, 
+	    'overrides order with circular #include');
+
+# Check parsing of objdump output on ia64 (local symbols
+# without versions and with visibility attribute)
+$obj = Dpkg::Shlibs::Objdump::Object->new;
+
+open $objdump, '<', "$srcdir/objdump.glib-ia64"
+  or die "$srcdir/objdump.glib-ia64: $!";
+$obj->_parse($objdump);
+close $objdump;
+
+$sym = $obj->get_symbol('IA__g_free');
+is_deeply( $sym, { name => 'IA__g_free', version => '',
+		   soname => 'libglib-2.0.so.0', section => '.text', dynamic => 1,
+		   debug => '', type => 'F', weak => '',
+		   local => 1, global => '', visibility => 'hidden',
+		   hidden => '', defined => 1 }, 
+		   'symbol with visibility without version' );
+

+ 9 - 0
scripts/t/200_Dpkg_Shlibs/ld.so.conf

@@ -0,0 +1,9 @@
+# Comment and empty line
+
+# Paths
+/nonexistant32
+/nonexistant/lib64
+
+include /nonexistant/*.conf
+include t.tmp/ld.so.conf.d/*.conf
+

+ 1 - 0
scripts/t/200_Dpkg_Shlibs/ld.so.conf.d/inf_recurse.conf

@@ -0,0 +1 @@
+include t.tmp/ld.so.conf

+ 1 - 0
scripts/t/200_Dpkg_Shlibs/ld.so.conf.d/normal.conf

@@ -0,0 +1 @@
+/usr/local/lib/

+ 1 - 0
scripts/t/200_Dpkg_Shlibs/ld.so.conf.d/recursive.conf

@@ -0,0 +1 @@
+include t.tmp/ld.so.conf_2

+ 1 - 0
scripts/t/200_Dpkg_Shlibs/ld.so.conf_2

@@ -0,0 +1 @@
+/nonexistant/lib128

+ 350 - 0
scripts/t/200_Dpkg_Shlibs/objdump.glib-ia64

@@ -0,0 +1,350 @@
+
+/usr/lib/libglib-2.0.so.0:     file format elf64-little
+architecture: ia64-elf64, flags 0x00000150:
+HAS_SYMS, DYNAMIC, D_PAGED
+start address 0x000000000002dc40
+
+Program Header:
+    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**16
+         filesz 0x0000000000158820 memsz 0x0000000000158820 flags r-x
+    LOAD off    0x0000000000158820 vaddr 0x0000000000168820 paddr 0x0000000000168820 align 2**16
+         filesz 0x0000000000001498 memsz 0x0000000000001a90 flags rw-
+ DYNAMIC off    0x0000000000158948 vaddr 0x0000000000168948 paddr 0x0000000000168948 align 2**3
+         filesz 0x00000000000001f0 memsz 0x00000000000001f0 flags rw-
+   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**3
+         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
+0x70000001 off    0x0000000000150e28 vaddr 0x0000000000150e28 paddr 0x0000000000150e28 align 2**3
+         filesz 0x00000000000079f8 memsz 0x00000000000079f8 flags r--
+
+Dynamic Section:
+  NEEDED      libc.so.6.1
+  SONAME      libglib-2.0.so.0
+  INIT        0x15070
+  FINI        0x106360
+  INIT_ARRAY  0x168820
+  INIT_ARRAYSZ 0x18
+  FINI_ARRAY  0x168838
+  FINI_ARRAYSZ 0x8
+  HASH        0x158
+  GNU_HASH    0x25c8
+  STRTAB      0xc4c0
+  SYMTAB      0x4a38
+  STRSZ       0x5deb
+  SYMENT      0x18
+  0x70000000  0x168dd8
+  PLTGOT      0x168dd8
+  PLTRELSZ    0xcd8
+  PLTREL      0x7
+  JMPREL      0x14398
+  RELA        0x12d18
+  RELASZ      0x1680
+  RELAENT     0x18
+  VERNEED     0x12ce8
+  VERNEEDNUM  0x1
+  VERSYM      0x122ac
+  RELACOUNT   0x60
+
+Version References:
+  required from libc.so.6.1:
+    0x0d696913 0x00 03 GLIBC_2.3
+    0x0d696912 0x00 02 GLIBC_2.2
+
+DYNAMIC SYMBOL TABLE:
+00000000000bbaa0 l    DF .text	00000000000006b0              .hidden IA__g_thread_pool_new
+000000000007b730 l    DF .text	0000000000000200              .hidden IA__g_option_group_free
+00000000000b2f30 l    DF .text	0000000000000060              .hidden IA__g_str_equal
+00000000000cd0c0 l    DF .text	0000000000000010              .hidden IA__g_direct_hash
+0000000000095660 l    DF .text	00000000000001d0              .hidden IA__g_scanner_warn
+00000000001062e0 l    DF .text	0000000000000080              .hidden __do_global_ctors_aux
+0000000000071fe0 l    DF .text	00000000000000f0              .hidden IA__g_free
+0000000000074a30 l    DF .text	0000000000000370              .hidden _g_log_fallback_handler
+0000000000077080 l    DF .text	0000000000000a20              .hidden IA__g_log_default_handler
+00000000000afc90 l    DF .text	0000000000000090              .hidden IA__g_str_hash
+0000000000095830 l    DF .text	00000000000001f0              .hidden IA__g_scanner_error
+00000000000d4d60 l    DF .text	0000000000000290              g_io_unix_get_flags
+00000000000d4a60 l    DF .text	0000000000000120              g_io_unix_set_flags
+00000000000d4b80 l    DF .text	0000000000000020              g_io_unix_free
+00000000000d4ba0 l    DF .text	00000000000000c0              g_io_unix_create_watch
+00000000000d4c60 l    DF .text	0000000000000100              g_io_unix_close
+00000000000d4ff0 l    DF .text	00000000000001f0              g_io_unix_seek
+00000000000d51e0 l    DF .text	0000000000000150              g_io_unix_write
+00000000000d5330 l    DF .text	0000000000000180              g_io_unix_read
+00000000000d4820 l    DF .text	0000000000000030              g_io_unix_finalize
+00000000000d4950 l    DF .text	0000000000000110              g_io_unix_dispatch
+00000000000d4850 l    DF .text	0000000000000080              g_io_unix_check
+00000000000d48d0 l    DF .text	0000000000000080              g_io_unix_prepare
+00000000000cd720 l    DF .text	0000000000000090              language_names_cache_free
+00000000000c89f0 l    DF .text	0000000000000090              charset_cache_free
+00000000000c20f0 l    DF .text	0000000000000050              interval_compare
+00000000000bb270 l    DF .text	0000000000000830              g_thread_pool_thread_proxy
+00000000000b3360 l    DF .text	0000000000000050              g_thread_fail
+00000000000b33b0 l    DF .text	00000000000000c0              gettime
+00000000000b8c70 l    DF .text	00000000000004a0              g_thread_cleanup
+00000000000b6790 l    DF .text	00000000000003b0              g_thread_create_proxy
+00000000000a37a0 l    DF .text	0000000000000320              private_thread_memory_cleanup
+000000000009a7d0 l    DF .text	00000000000000e0              iter_compare
+0000000000094c10 l    DF .text	0000000000000060              g_scanner_destroy_symbol_table_entry
+0000000000095f50 l    DF .text	00000000000001b0              g_scanner_msg_handler
+0000000000096100 l    DF .text	00000000000000a0              g_scanner_key_equal
+0000000000093210 l    DF .text	0000000000000080              g_scanner_key_hash
+0000000000093290 l    DF .text	00000000000000c0              g_scanner_foreach_internal
+0000000000092510 l    DF .text	00000000000004a0              interpolate_replacement
+000000000008cd60 l    DF .text	0000000000000050              literal_replacement
+000000000008cd00 l    DF .text	0000000000000060              free_interpolation_data
+0000000000089190 l    DF .text	0000000000000040              relation_delete_value_tuple
+0000000000089c20 l    DF .text	0000000000000030              g_relation_free_array
+0000000000089690 l    DF .text	0000000000000210              g_relation_delete_tuple
+00000000000895a0 l    DF .text	00000000000000f0              g_relation_select_tuple
+0000000000088c30 l    DF .text	00000000000000a0              g_relation_print_index
+0000000000088cd0 l    DF .text	0000000000000170              g_relation_print_one
+00000000000889a0 l    DF .text	0000000000000020              tuple_hash_2
+0000000000088940 l    DF .text	0000000000000060              tuple_equal_2
+000000000007bc50 l    DF .text	0000000000000050              dgettext_swapped
+00000000000787b0 l    DF .text	0000000000000040              g_node_find_func
+0000000000071570 l    DF .text	0000000000000200              profiler_try_realloc
+0000000000071770 l    DF .text	0000000000000150              profiler_try_malloc
+0000000000073410 l    DF .text	0000000000000190              profiler_calloc
+00000000000718c0 l    DF .text	00000000000001c0              profiler_free
+0000000000073380 l    DF .text	0000000000000090              profiler_realloc
+00000000000735a0 l    DF .text	0000000000000090              profiler_malloc
+0000000000071a80 l    DF .text	00000000000000d0              fallback_calloc
+000000000005a2b0 l    DF .text	0000000000000040              g_source_callback_get
+000000000005d650 l    DF .text	00000000000000e0              g_source_callback_unref
+000000000005a290 l    DF .text	0000000000000020              g_source_callback_ref
+000000000005a340 l    DF .text	00000000000000c0              g_idle_dispatch
+000000000005a330 l    DF .text	0000000000000010              g_idle_check
+000000000005a310 l    DF .text	0000000000000020              g_idle_prepare
+000000000005a400 l    DF .text	00000000000000c0              g_child_watch_dispatch
+000000000005a5c0 l    DF .text	0000000000000020              g_child_watch_check
+000000000005a5e0 l    DF .text	0000000000000030              g_child_watch_prepare
+0000000000060390 l    DF .text	0000000000000160              g_timeout_dispatch
+00000000000604f0 l    DF .text	00000000000000f0              g_timeout_check
+00000000000605e0 l    DF .text	0000000000000310              g_timeout_prepare
+000000000005cc20 l    DF .text	0000000000000030              g_main_dispatch_free
+000000000005b130 l    DF .text	00000000000000b0              g_child_watch_signal_handler
+00000000000619f0 l    DF .text	00000000000002e0              child_watch_helper_thread
+000000000004d830 l    DF .text	00000000000000b0              g_key_file_key_value_pair_free
+0000000000041860 l    DF .text	0000000000000090              default_finalize_hook
+000000000002b370 l    DF .text	0000000000000090              filename_charset_cache_free
+000000000001fe80 l    DF .text	0000000000000440              text_raw_cb
+0000000000020660 l    DF .text	0000000000000480              end_element_raw_cb
+0000000000026110 l    DF .text	0000000000001cf0              start_element_raw_cb
+000000000001e790 l    DF .text	0000000000000060              parse_data_free
+000000000001e6e0 l    DF .text	00000000000000b0              bookmark_app_info_free
+000000000001e960 l    DF .text	0000000000000260              bookmark_item_free
+000000000001c300 l    DF .text	0000000000000020              stack_trace_sigchld
+0000000000019a00 l    DF .text	0000000000000070              g_async_queue_invert_compare
+0000000000016be0 l    DF .text	0000000000000080              __do_jv_register_classes
+0000000000016b20 l    DF .text	00000000000000b0              __do_global_dtors_aux
+0000000000016aa0 l    DF .text	0000000000000070              gmon_initializer
+0000000000000000      DF *UND*	0000000000000370  GLIBC_2.2   getpwuid
+0000000000000000      DF *UND*	0000000000000550  GLIBC_2.2   freopen
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   __strtod_internal
+0000000000000000      DF *UND*	0000000000000240  GLIBC_2.2   feof
+0000000000000000      DF *UND*	0000000000000450  GLIBC_2.2   localeconv
+0000000000000000      DF *UND*	00000000000001e0  GLIBC_2.2   strcpy
+0000000000000000      DF *UND*	0000000000000200  GLIBC_2.2   raise
+0000000000000000      DO *UND*	0000000000000008  GLIBC_2.2   environ
+0000000000000000      DF *UND*	0000000000000030  GLIBC_2.2   getuid
+0000000000000000      DF *UND*	0000000000000180  GLIBC_2.2   waitpid
+0000000000000000      DF *UND*	0000000000000100  GLIBC_2.2   strcasecmp
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   select
+0000000000000000      DF *UND*	0000000000000110  GLIBC_2.2   closedir
+0000000000000000      DF *UND*	0000000000000440  GLIBC_2.2   fwrite
+0000000000000000      DF *UND*	00000000000001d0  GLIBC_2.2   rewinddir
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   close
+0000000000000000      DF *UND*	0000000000000280  GLIBC_2.2   strstr
+0000000000000000      DF *UND*	0000000000000080  GLIBC_2.2   time
+0000000000000000      DF *UND*	0000000000000520  GLIBC_2.2   fdopen
+0000000000000000  w   D  *UND*	0000000000000000              __gmon_start__
+0000000000000000  w   D  *UND*	0000000000000000              _Jv_RegisterClasses
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   wcsxfrm
+0000000000000000      DF *UND*	00000000000000c0  GLIBC_2.2   strncasecmp
+0000000000000000      DF *UND*	00000000000000d0  GLIBC_2.2   remove
+0000000000000000      DF *UND*	00000000000004f0  GLIBC_2.2   malloc
+0000000000000000      DF *UND*	0000000000000080  GLIBC_2.2   execve
+0000000000000000      DF *UND*	00000000000000b0  GLIBC_2.2   fprintf
+0000000000000000      DF *UND*	0000000000000200  GLIBC_2.2   setpwent
+0000000000000000      DF *UND*	0000000000000100  GLIBC_2.2   nl_langinfo
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   chdir
+0000000000000000      DF *UND*	0000000000000100  GLIBC_2.2   gethostname
+0000000000000000  w   DO *UND*	0000000000000008  GLIBC_2.2   _environ
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   rmdir
+0000000000000000      DF *UND*	0000000000000390  GLIBC_2.2   fputc
+0000000000000000      DF *UND*	0000000000000170  GLIBC_2.2   poll
+0000000000000000      DF *UND*	00000000000003e0  GLIBC_2.2   getcwd
+0000000000000000      DO *UND*	0000000000000008  GLIBC_2.2   stdin
+0000000000000000      DF *UND*	00000000000004f0  GLIBC_2.2   getpwnam_r
+0000000000000000      DF *UND*	0000000000000520  GLIBC_2.2   memmove
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   __strtoul_internal
+0000000000000000      DO *UND*	0000000000000008  GLIBC_2.2   stdout
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   strncmp
+0000000000000000      DF *UND*	0000000000000320  GLIBC_2.2   vasprintf
+0000000000000000      DF *UND*	0000000000000210  GLIBC_2.2   endpwent
+0000000000000000      DF *UND*	00000000000001f0  GLIBC_2.2   fcntl
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   dup2
+0000000000000000      DF *UND*	00000000000007e0  GLIBC_2.2   fork
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   gmtime
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   readlink
+0000000000000000      DF *UND*	0000000000000080  GLIBC_2.3   __ctype_toupper_loc
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   lseek
+0000000000000000      DF *UND*	00000000000000c0  GLIBC_2.2   __fxstat
+0000000000000000      DF *UND*	00000000000000b0  GLIBC_2.2   fscanf
+0000000000000000      DO *UND*	0000000000000008  GLIBC_2.2   __environ
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   munmap
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   strftime
+0000000000000000      DF *UND*	00000000000003a0  GLIBC_2.2   fread
+0000000000000000      DF *UND*	0000000000007090  GLIBC_2.2   vfprintf
+0000000000000000      DF *UND*	00000000000000b0  GLIBC_2.2   snprintf
+0000000000000000      DF *UND*	0000000000000330  GLIBC_2.2   iconv_open
+0000000000000000      DF *UND*	0000000000000080  GLIBC_2.3   __ctype_b_loc
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   nanosleep
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   pipe
+0000000000000000      DF *UND*	0000000000000090  GLIBC_2.2   strpbrk
+0000000000000000      DF *UND*	0000000000000640  GLIBC_2.2   realloc
+0000000000000000      DF *UND*	0000000000000240  GLIBC_2.2   ferror
+0000000000000000      DF *UND*	00000000000004f0  GLIBC_2.2   getpwuid_r
+0000000000000000      DF *UND*	0000000000000030  GLIBC_2.2   strcmp
+0000000000000000      DF *UND*	00000000000000e0  GLIBC_2.2   setenv
+0000000000000000      DF *UND*	0000000000000650  GLIBC_2.2   fclose
+0000000000000000  w   DF *UND*	0000000000000220  GLIBC_2.2   __cxa_finalize
+0000000000000000      DF *UND*	0000000000000020  GLIBC_2.2   __errno_location
+0000000000000000      DF *UND*	00000000000002c0  GLIBC_2.2   exit
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   open
+0000000000000000      DF *UND*	0000000000000590  GLIBC_2.2   abort
+0000000000000000      DF *UND*	0000000000000400  GLIBC_2.2   fputs
+0000000000000000      DF *UND*	00000000000000a0  GLIBC_2.2   sigemptyset
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   localtime_r
+0000000000000000      DF *UND*	00000000000000b0  GLIBC_2.2   sprintf
+0000000000000000      DF *UND*	00000000000002c0  GLIBC_2.2   unsetenv
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   mmap
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   mkdir
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   creat
+0000000000000000      DF *UND*	00000000000000d0  GLIBC_2.2   getpid
+0000000000000000      DF *UND*	0000000000000170  GLIBC_2.2   strerror
+0000000000000000      DF *UND*	0000000000000220  GLIBC_2.2   memcmp
+0000000000000000      DF *UND*	0000000000000320  GLIBC_2.2   qsort
+0000000000000000      DF *UND*	0000000000000c70  GLIBC_2.2   sysconf
+0000000000000000      DF *UND*	0000000000000190  GLIBC_2.2   bsearch
+0000000000000000      DF *UND*	00000000000001b0  GLIBC_2.2   signal
+0000000000000000      DF *UND*	00000000000000c0  GLIBC_2.2   __xstat
+0000000000000000      DF *UND*	00000000000000c0  GLIBC_2.2   __lxstat
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   wcscoll
+0000000000000000      DF *UND*	0000000000000160  GLIBC_2.2   vsprintf
+0000000000000000      DF *UND*	0000000000000130  GLIBC_2.2   vsnprintf
+0000000000000000      DF *UND*	00000000000003e0  GLIBC_2.2   strncpy
+0000000000000000      DF *UND*	00000000000002e0  GLIBC_2.2   getenv
+0000000000000000      DF *UND*	0000000000000120  GLIBC_2.2   strchr
+0000000000000000      DF *UND*	00000000000008c0  GLIBC_2.2   calloc
+0000000000000000      DF *UND*	00000000000000a0  GLIBC_2.2   __cxa_atexit
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   write
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   stpcpy
+0000000000000000      DF *UND*	0000000000000450  GLIBC_2.2   fgets
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   rename
+0000000000000000      DF *UND*	0000000000000310  GLIBC_2.2   __uflow
+0000000000000000      DF *UND*	0000000000000410  GLIBC_2.2   memset
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   fopen
+0000000000000000      DF *UND*	0000000000000050  GLIBC_2.2   __strtol_internal
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   unlink
+0000000000000000      DF *UND*	0000000000000430  GLIBC_2.2   iconv
+0000000000000000      DF *UND*	00000000000001b0  GLIBC_2.2   perror
+0000000000000000      DF *UND*	0000000000000880  GLIBC_2.2   execvp
+0000000000000000      DF *UND*	0000000000000330  GLIBC_2.2   ungetc
+0000000000000000      DF *UND*	0000000000000140  GLIBC_2.2   _exit
+0000000000000000      DF *UND*	0000000000000080  GLIBC_2.3   __ctype_tolower_loc
+0000000000000000      DF *UND*	0000000000000070  GLIBC_2.2   bindtextdomain
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   chmod
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   timegm
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   read
+0000000000000000      DF *UND*	0000000000000300  GLIBC_2.2   readdir
+0000000000000000      DF *UND*	0000000000000300  GLIBC_2.2   free
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   dcgettext
+0000000000000000      DF *UND*	00000000000000e0  GLIBC_2.2   strrchr
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   access
+0000000000000000      DF *UND*	0000000000000390  GLIBC_2.2   fflush
+0000000000000000      DF *UND*	0000000000000070  GLIBC_2.2   bind_textdomain_codeset
+0000000000000000      DF *UND*	00000000000001c0  GLIBC_2.2   opendir
+0000000000000000      DF *UND*	0000000000000530  GLIBC_2.2   strsignal
+0000000000000000      DF *UND*	0000000000000070  GLIBC_2.2   isatty
+0000000000000000      DF *UND*	0000000000000130  GLIBC_2.2   posix_memalign
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   gettimeofday
+0000000000000000      DF *UND*	00000000000000a0  GLIBC_2.2   iconv_close
+0000000000000000      DF *UND*	0000000000000040  GLIBC_2.2   dup
+0000000000000000      DF *UND*	0000000000000540  GLIBC_2.2   memcpy
+0000000000000000      DO *UND*	0000000000000008  GLIBC_2.2   stderr
+0000000000000000      DF *UND*	0000000000000030  GLIBC_2.2   getppid
+0000000000000000      DF *UND*	0000000000000100  GLIBC_2.2   strlen
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   execv
+0000000000000000      DF *UND*	0000000000000f50  GLIBC_2.2   setlocale
+0000000000000000      DF *UND*	0000000000000060  GLIBC_2.2   sigaction
+00000000000909e0 g    DF .text	0000000000000310  Base        g_regex_match_full
+0000000000038400 g    DF .text	0000000000000660  Base        g_date_strftime
+0000000000017530 g    DF .text	00000000000000f0  Base        g_ptr_array_add
+00000000000c6930 g    DF .text	00000000000001e0  Base        g_utf8_strreverse
+0000000000039650 g    DF .text	0000000000000030  Base        g_date_set_time
+00000000000cab10 g    DF .text	0000000000000710  Base        g_utf8_collate_key_for_filename
+00000000000c26f0 g    DF .text	0000000000000160  Base        g_unichar_type
+000000000002a930 g    DF .text	0000000000000430  Base        g_uri_list_extract_uris
+00000000000cf850 g    DF .text	0000000000000350  Base        g_get_system_data_dirs
+000000000008b450 g    DF .text	0000000000000070  Base        g_rand_new_with_seed_array
+00000000000a7410 g    DF .text	0000000000000080  Base        g_slist_concat
+0000000000033c50 g    DF .text	0000000000000020  Base        g_date_valid_weekday
+000000000003f090 g    DF .text	0000000000000190  Base        g_hash_table_get_values
+0000000000058710 g    DF .text	0000000000000010  Base        g_list_pop_allocator
+000000000008c9a0 g    DF .text	00000000000000b0  Base        g_match_info_is_partial_match
+00000000000d3620 g    DF .text	0000000000000290  Base        g_get_user_name
+00000000000a84d0 g    DF .text	0000000000000030  Base        g_slist_free_1
+00000000000cccc0 g    DF .text	00000000000002b0  Base        g_unicode_canonical_decomposition
+00000000000656e0 g    DF .text	0000000000000550  Base        g_main_context_unref
+00000000000d42b0 g    DF .text	0000000000000100  Base        g_vsprintf
+0000000000079f90 g    DF .text	00000000000000e0  Base        g_node_get_root
+0000000000016df0 g    DF .text	0000000000000130  Base        g_ptr_array_remove_index_fast
+000000000007b3b0 g    DF .text	0000000000000080  Base        g_option_group_set_parse_hooks
+00000000000b2c80 g    DF .text	0000000000000170  Base        g_string_chunk_clear
+0000000000021620 g    DF .text	0000000000000040  Base        g_bookmark_file_error_quark
+0000000000088490 g    DF .text	0000000000000110  Base        g_queue_sort
+00000000000c7c00 g    DF .text	0000000000000530  Base        g_utf16_to_utf8
+00000000000197e0 g    DF .text	0000000000000050  Base        g_byte_array_prepend
+0000000000053510 g    DF .text	0000000000000580  Base        g_key_file_get_string_list
+0000000000169a40 g    DO .sdata	0000000000000008  Base        glib_mem_profiler_table
+00000000000a8760 g    DF .text	00000000000000d0  Base        g_slist_remove_link
+00000000000a8130 g    DF .text	0000000000000060  Base        g_slist_prepend
+0000000000063bf0 g    DF .text	0000000000000390  Base        g_main_context_find_source_by_user_data
+000000000005c540 g    DF .text	00000000000000d0  Base        g_main_loop_is_running
+000000000003c5e0 g    DF .text	0000000000000030  Base        g_mkstemp
+00000000000b0440 g    DF .text	0000000000000140  Base        g_string_set_size
+0000000000088160 g    DF .text	0000000000000110  Base        g_queue_insert_after
+00000000000738a0 g    DF .text	0000000000000150  Base        g_log_set_default_handler
+0000000000059c30 g    DF .text	00000000000000b0  Base        g_list_delete_link
+0000000000058a10 g    DF .text	0000000000000090  Base        g_list_position
+0000000000059110 g    DF .text	0000000000000100  Base        g_list_find_custom
+00000000000b0990 g    DF .text	00000000000000f0  Base        g_string_ascii_down
+00000000000629a0 g    DF .text	0000000000000130  Base        g_main_loop_new
+000000000005acb0 g    DF .text	00000000000000b0  Base        g_source_get_context
+0000000000033c00 g    DF .text	0000000000000020  Base        g_date_valid_year
+00000000000a7d90 g    DF .text	0000000000000030  Base        g_slist_insert_sorted
+000000000009f6a0 g    DF .text	0000000000000f20  Base        g_shell_parse_argv
+00000000000bca30 g    DF .text	00000000000000f0  Base        g_timer_stop
+0000000000099ec0 g    DF .text	0000000000000120  Base        g_scanner_peek_next_token
+000000000002d5a0 g    DF .text	00000000000000f0  Base        g_filename_display_basename
+00000000000305c0 g    DF .text	0000000000000580  Base        g_dataset_id_get_data
+0000000000064a50 g    DF .text	0000000000000480  Base        g_source_attach
+000000000003e5d0 g    DF .text	0000000000000360  Base        g_mkdir_with_parents
+000000000001de50 g    DF .text	0000000000000110  Base        g_bookmark_file_has_item
+0000000000065050 g    DF .text	00000000000001c0  Base        g_child_watch_add_full
+00000000000a8830 g    DF .text	0000000000000050  Base        g_freopen
+00000000000a8730 g    DF .text	0000000000000030  Base        g_slist_alloc
+0000000000054a60 g    DF .text	0000000000000480  Base        g_key_file_get_locale_string
+0000000000094fd0 g    DF .text	00000000000001b0  Base        g_scanner_input_file
+0000000000093660 g    DF .text	00000000000000a0  Base        g_scanner_set_scope
+0000000000022780 g    DF .text	0000000000000180  Base        g_bookmark_file_get_visited
+000000000002f280 g    DF .text	00000000000003a0  Base        g_datalist_id_get_data
+0000000000040000 g    DF .text	00000000000000e0  Base        g_hash_table_new_full
+00000000000d2f40 g    DF .text	0000000000000260  Base        g_get_user_config_dir
+0000000000059700 g    DF .text	0000000000000280  Base        g_list_insert_before
+0000000000079270 g    DF .text	00000000000000f0  Base        g_node_n_children
+00000000000d0680 g    DF .text	0000000000000460  Base        g_get_user_cache_dir
+000000000006a5a0 g    DF .text	00000000000000d0  Base        g_markup_parse_context_get_element
+00000000000aefe0 g    DF .text	00000000000000a0  Base        g_strndup
+
+

File diff suppressed because it is too large
+ 2276 - 0
scripts/t/200_Dpkg_Shlibs/objdump.libc6-2.3


File diff suppressed because it is too large
+ 2345 - 0
scripts/t/200_Dpkg_Shlibs/objdump.libc6-2.6


+ 4 - 0
scripts/t/200_Dpkg_Shlibs/symbols.fake-1

@@ -0,0 +1,4 @@
+libfake.so.1 libfake1 #MINVER#
+ symbol1_fake1@Base 1.0
+ symbol2_fake1@Base 1.0
+ symbol3_fake1@Base 1.0

+ 8 - 0
scripts/t/200_Dpkg_Shlibs/symbols.fake-2

@@ -0,0 +1,8 @@
+#include "symbols.include-2"
+# This is just a comment
+libfake.so.1 libfake1 #MINVER#
+# The alternate dependency is below
+| libvirtualfake
+ symbol1_fake2@Base 1.0 1
+ symbol2_fake2@Base 1.0
+ symbol3_fake2@Base 1.0

+ 7 - 0
scripts/t/200_Dpkg_Shlibs/symbols.include-1

@@ -0,0 +1,7 @@
+libfake.so.1 libfake1
+ symbol1_fake1@Base 0.9
+ symbol2_fake1@Base 0.9
+ symbol_before@Base 0.9
+#include "symbols.fake-1"
+ symbol3_fake1@Base 1.1
+ symbol_after@Base 1.1

+ 3 - 0
scripts/t/200_Dpkg_Shlibs/symbols.include-2

@@ -0,0 +1,3 @@
+libfake.so.1 libfake1
+ symbol1_fake2@Base 0.5
+#include "symbols.fake-2"