Sfoglia il codice sorgente

Merge branch 'debian/sid' into debian/experimental

Conflicts:
	apt-pkg/contrib/strutl.cc
	apt-pkg/deb/dpkgpm.cc
	configure.ac
	debian/changelog
	doc/po/apt-doc.pot
	po/apt-all.pot
	po/ar.po
	po/ast.po
	po/bg.po
	po/bs.po
	po/ca.po
	po/cs.po
	po/cy.po
	po/da.po
	po/de.po
	po/dz.po
	po/el.po
	po/es.po
	po/eu.po
	po/fi.po
	po/fr.po
	po/gl.po
	po/hu.po
	po/it.po
	po/ja.po
	po/km.po
	po/ko.po
	po/ku.po
	po/lt.po
	po/mr.po
	po/nb.po
	po/ne.po
	po/nl.po
	po/nn.po
	po/pl.po
	po/pt.po
	po/pt_BR.po
	po/ro.po
	po/ru.po
	po/sk.po
	po/sl.po
	po/sv.po
	po/th.po
	po/tl.po
	po/uk.po
	po/vi.po
	po/zh_CN.po
	po/zh_TW.po
	test/integration/framework
	test/integration/test-bug-602412-dequote-redirect
	test/integration/test-ubuntu-bug-346386-apt-get-update-paywall
	test/interactive-helper/aptwebserver.cc
	test/interactive-helper/makefile
Michael Vogt 13 anni fa
parent
commit
d7a4635391
100 ha cambiato i file con 4669 aggiunte e 10663 eliminazioni
  1. 0 6
      .bzr-builddeb/default.conf
  2. 37 0
      .gitignore
  3. 5 0
      .travis.yml
  4. 1 1
      Makefile
  5. 0 7325
      abicheck/abi-compliance-checker.pl
  6. 6 1
      abicheck/run_abi_test
  7. 3 0
      apt-inst/contrib/arfile.cc
  8. 0 1
      apt-inst/contrib/extracttar.cc
  9. 1 0
      apt-inst/makefile
  10. 53 8
      apt-pkg/acquire-item.cc
  11. 2 0
      apt-pkg/acquire-item.h
  12. 10 3
      apt-pkg/acquire-worker.cc
  13. 16 7
      apt-pkg/algorithms.cc
  14. 4 3
      apt-pkg/algorithms.h
  15. 2 2
      apt-pkg/aptconfiguration.cc
  16. 1 0
      apt-pkg/cacheiterators.h
  17. 0 1
      apt-pkg/cacheset.h
  18. 8 0
      apt-pkg/cdrom.cc
  19. 1 1
      apt-pkg/cdrom.h
  20. 2 1
      apt-pkg/contrib/cdromutl.cc
  21. 1 1
      apt-pkg/contrib/configuration.cc
  22. 6 4
      apt-pkg/contrib/error.cc
  23. 35 6
      apt-pkg/contrib/error.h
  24. 114 106
      apt-pkg/contrib/fileutl.cc
  25. 4 0
      apt-pkg/contrib/fileutl.h
  26. 1 1
      apt-pkg/contrib/gpgv.cc
  27. 12 3
      apt-pkg/contrib/gpgv.h
  28. 3 1
      apt-pkg/contrib/sha2.h
  29. 6 6
      apt-pkg/contrib/sha2_internal.cc
  30. 10 9
      apt-pkg/contrib/strutl.cc
  31. 24 86
      apt-pkg/deb/deblistparser.cc
  32. 22 2
      apt-pkg/deb/debmetaindex.cc
  33. 73 34
      apt-pkg/deb/dpkgpm.cc
  34. 3 1
      apt-pkg/deb/dpkgpm.h
  35. 75 15
      apt-pkg/depcache.cc
  36. 17 13
      apt-pkg/depcache.h
  37. 17 6
      apt-pkg/indexcopy.cc
  38. 2 8
      apt-pkg/indexcopy.h
  39. 6 11
      apt-pkg/indexrecords.cc
  40. 105 119
      apt-pkg/orderlist.cc
  41. 73 48
      apt-pkg/packagemanager.cc
  42. 12 0
      apt-pkg/pkgcache.cc
  43. 3 1
      apt-pkg/pkgcachegen.cc
  44. 18 7
      apt-pkg/policy.cc
  45. 1 1
      apt-pkg/tagfile.h
  46. 1 1
      apt-pkg/vendorlist.cc
  47. 1 0
      buildlib/apti18n.h.in
  48. 2 2
      buildlib/configure.mak
  49. 1 1
      buildlib/copy.mak
  50. 8 9
      buildlib/defaults.mak
  51. 2 2
      buildlib/library.mak
  52. 7 5
      buildlib/po4a_manpage.mak
  53. 6 1
      buildlib/podomain.mak
  54. 123 53
      cmdline/apt-cache.cc
  55. 22 12
      cmdline/apt-cdrom.cc
  56. 39 10
      cmdline/apt-get.cc
  57. 145 47
      cmdline/apt-key
  58. 2 2
      cmdline/apt-mark.cc
  59. 1 1
      cmdline/makefile
  60. 3 7
      configure.in
  61. 93 0
      debian/apt.auto-removal.sh
  62. 0 3
      debian/apt.conf.autoremove
  63. 1 0
      debian/apt.dirs
  64. 13 5
      debian/apt.postinst
  65. 235 10
      debian/changelog
  66. 7 7
      debian/control
  67. 6 0
      debian/gbp.conf
  68. 1 5
      debian/libapt-inst1.5.symbols
  69. 52 69
      debian/libapt-pkg4.13.symbols
  70. 27 19
      debian/rules
  71. 522 146
      doc/Doxyfile.in
  72. 8 0
      doc/apt-cdrom.8.xml
  73. 1 1
      doc/apt-verbatim.ent
  74. 11 6
      doc/apt.conf.5.xml
  75. 38 0
      doc/en/makefile
  76. 1 1
      doc/examples/configure-index
  77. 19 53
      doc/makefile
  78. 147 138
      doc/po/apt-doc.pot
  79. 179 180
      doc/po/de.po
  80. 161 162
      doc/po/es.po
  81. 168 169
      doc/po/fr.po
  82. 213 186
      doc/po/it.po
  83. 160 160
      doc/po/ja.po
  84. 153 153
      doc/po/pl.po
  85. 167 166
      doc/po/pt.po
  86. 153 153
      doc/po/pt_BR.po
  87. 5 1
      doc/sources.list.5.xml
  88. 2 1
      ftparchive/writer.cc
  89. 1 0
      methods/ftp.cc
  90. 8 9
      methods/gpgv.cc
  91. 27 28
      methods/http.cc
  92. 1 1
      methods/http.h
  93. 25 2
      methods/https.cc
  94. 1 1
      methods/makefile
  95. 3 0
      methods/mirror.cc
  96. 2 0
      methods/rsh.cc
  97. 7 1
      po/LINGUAS
  98. 445 409
      po/apt-all.pot
  99. 448 416
      po/ar.po
  100. 0 0
      po/ast.po

+ 0 - 6
.bzr-builddeb/default.conf

@@ -1,6 +0,0 @@
-[BUILDDEB]
-native = true
-
-[HOOKS]
-pre-export = ./prepare-release pre-export
-post-build = ./prepare-release post-build

+ 37 - 0
.gitignore

@@ -0,0 +1,37 @@
+# build artifacts
+/aclocal.m4
+/autom4te.cache/
+/build/
+/buildlib/config.guess
+/buildlib/config.sub
+/configure
+
+# copy of COPYING
+/debian/copyright
+
+# generated files in the process to build all
+# apt man pages and other documentation
+/doc/*/
+!/doc/examples/
+!/doc/po/
+!/doc/en/makefile
+
+# package building artifacts
+/debian/*.log
+/debian/*.substvars
+/debian/*.debhelper
+/debian/files
+/debian/apt/
+/debian/apt-doc/
+/debian/apt-utils/
+/debian/libapt-pkg*/
+/debian/libapt-inst*/
+/debian/libapt-pkg-dev/
+/debian/libapt-pkg-doc/
+/debian/apt-transport-https/
+
+# generated from *.in files
+/doc/examples/sources.list
+/debian/libapt-pkg*.install
+/debian/libapt-inst*.install
+/debian/libapt-pkg-dev.install

+ 5 - 0
.travis.yml

@@ -0,0 +1,5 @@
+language: cpp
+before_install:
+ - sudo apt-get update -q
+ - sudo apt-get install -q dpkg-dev debhelper libdb-dev gettext libcurl4-gnutls-dev zlib1g-dev libbz2-dev xsltproc docbook-xsl docbook-xml po4a autotools-dev autoconf automake doxygen debiandoc-sgml
+script: make && make test && test/integration/run-tests

+ 1 - 1
Makefile

@@ -19,7 +19,7 @@ all headers library clean veryclean binary program doc manpages debiandoc test u
 	$(MAKE) -C dselect $@
 	$(MAKE) -C dselect $@
 	$(MAKE) -C doc $@
 	$(MAKE) -C doc $@
 	$(MAKE) -C po $@
 	$(MAKE) -C po $@
-	$(MAKE) -C test $@
+	$(MAKE) -C test $@ 
 
 
 all headers library clean veryclean binary program doc manpages debiandoc test update-po: startup dirs
 all headers library clean veryclean binary program doc manpages debiandoc test update-po: startup dirs
 
 

File diff suppressed because it is too large
+ 0 - 7325
abicheck/abi-compliance-checker.pl


+ 6 - 1
abicheck/run_abi_test

@@ -5,10 +5,15 @@ if [ ! -d ../build ]; then
 	exit 1
 	exit 1
 fi
 fi
 
 
+if [ ! -x "$(which abi-compliance-checker 2>/dev/null )" ]; then
+	echo "Please install the 'abi-compliance-checker' package"
+	exit 1
+fi
+
 LIBPATH=$(find /usr/lib/ -type f  -name "libapt-*.so.*" -printf %p\\\\n)
 LIBPATH=$(find /usr/lib/ -type f  -name "libapt-*.so.*" -printf %p\\\\n)
 sed s#@installed_libapt@#$LIBPATH# apt_installed.xml.in > apt_installed.xml
 sed s#@installed_libapt@#$LIBPATH# apt_installed.xml.in > apt_installed.xml
 
 
 BUILDPATH=$(readlink -f ../build)
 BUILDPATH=$(readlink -f ../build)
 sed s#@build_path@#$BUILDPATH# apt_build.xml.in > apt_build.xml
 sed s#@build_path@#$BUILDPATH# apt_build.xml.in > apt_build.xml
 
 
-perl abi-compliance-checker.pl -l apt -d1 apt_installed.xml -d2 apt_build.xml
+abi-compliance-checker -l apt -d1 apt_installed.xml -d2 apt_build.xml

+ 3 - 0
apt-inst/contrib/arfile.cc

@@ -106,7 +106,10 @@ bool ARArchive::LoadHeaders()
 	    return _error->Error(_("Invalid archive member header"));
 	    return _error->Error(_("Invalid archive member header"));
 	 }
 	 }
 	 if (File.Read(S,Len) == false)
 	 if (File.Read(S,Len) == false)
+	 {
+	    delete Memb;
 	    return false;
 	    return false;
+	 }
 	 S[Len] = 0;
 	 S[Len] = 0;
 	 Memb->Name = S;
 	 Memb->Name = S;
 	 Memb->Size -= Len;
 	 Memb->Size -= Len;

+ 0 - 1
apt-inst/contrib/extracttar.cc

@@ -63,7 +63,6 @@ ExtractTar::ExtractTar(FileFd &Fd,unsigned long Max,string DecompressionProgram)
 
 
 {
 {
    GZPid = -1;
    GZPid = -1;
-   InFd = -1;
    Eof = false;
    Eof = false;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 1 - 0
apt-inst/makefile

@@ -18,6 +18,7 @@ MAJOR=1.5
 MINOR=0
 MINOR=0
 SLIBS=$(PTHREADLIB) -lapt-pkg
 SLIBS=$(PTHREADLIB) -lapt-pkg
 APT_DOMAIN:=libapt-inst$(MAJOR)
 APT_DOMAIN:=libapt-inst$(MAJOR)
+LIBRARYDEPENDS=$(LIB)/libapt-pkg.so
 
 
 # Source code for the contributed non-core things
 # Source code for the contributed non-core things
 SOURCE = contrib/extracttar.cc contrib/arfile.cc
 SOURCE = contrib/extracttar.cc contrib/arfile.cc

+ 53 - 8
apt-pkg/acquire-item.cc

@@ -1067,8 +1067,7 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,				/*{{{*/
       
       
    string Final = _config->FindDir("Dir::State::lists");
    string Final = _config->FindDir("Dir::State::lists");
    Final += URItoFileName(RealURI);
    Final += URItoFileName(RealURI);
-   struct stat Buf;
-   if (stat(Final.c_str(),&Buf) == 0)
+   if (RealFileExists(Final) == true)
    {
    {
       // File was already in place.  It needs to be re-downloaded/verified
       // File was already in place.  It needs to be re-downloaded/verified
       // because Release might have changed, we do give it a differnt
       // because Release might have changed, we do give it a differnt
@@ -1080,6 +1079,19 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,				/*{{{*/
    }
    }
 
 
    QueueURI(Desc);
    QueueURI(Desc);
+}
+									/*}}}*/
+pkgAcqMetaSig::~pkgAcqMetaSig()						/*{{{*/
+{
+   // if the file was never queued undo file-changes done in the constructor
+   if (QueueCounter == 1 && Status == StatIdle && FileSize == 0 && Complete == false &&
+	 LastGoodSig.empty() == false)
+   {
+      string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
+      if (RealFileExists(Final) == false && RealFileExists(LastGoodSig) == true)
+	 Rename(LastGoodSig, Final);
+   }
+
 }
 }
 									/*}}}*/
 									/*}}}*/
 // pkgAcqMetaSig::Custom600Headers - Insert custom request headers	/*{{{*/
 // pkgAcqMetaSig::Custom600Headers - Insert custom request headers	/*{{{*/
@@ -1300,7 +1312,14 @@ void pkgAcqMetaIndex::RetrievalDone(string Message)			/*{{{*/
       string FinalFile = _config->FindDir("Dir::State::lists");
       string FinalFile = _config->FindDir("Dir::State::lists");
       FinalFile += URItoFileName(RealURI);
       FinalFile += URItoFileName(RealURI);
       if (SigFile == DestFile)
       if (SigFile == DestFile)
+      {
 	 SigFile = FinalFile;
 	 SigFile = FinalFile;
+	 // constructor of pkgAcqMetaClearSig moved it out of the way,
+	 // now move it back in on IMS hit for the 'old' file
+	 string const OldClearSig = DestFile + ".reverify";
+	 if (RealFileExists(OldClearSig) == true)
+	    Rename(OldClearSig, FinalFile);
+      }
       DestFile = FinalFile;
       DestFile = FinalFile;
    }
    }
    Complete = true;
    Complete = true;
@@ -1373,9 +1392,20 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
    {
    {
       HashString ExpectedIndexHash;
       HashString ExpectedIndexHash;
       const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
       const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
+      bool compressedAvailable = false;
       if (Record == NULL)
       if (Record == NULL)
       {
       {
-	 if (verify == true && (*Target)->IsOptional() == false)
+	 if ((*Target)->IsOptional() == true)
+	 {
+	    std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+	    for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+	       if (MetaIndexParser->Exists(string((*Target)->MetaKey).append(".").append(*t)) == true)
+	       {
+		  compressedAvailable = true;
+		  break;
+	       }
+	 }
+	 else if (verify == true)
 	 {
 	 {
 	    Status = StatAuthError;
 	    Status = StatAuthError;
 	    strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str());
 	    strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str());
@@ -1404,7 +1434,7 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
 	 if ((*Target)->IsSubIndex() == true)
 	 if ((*Target)->IsSubIndex() == true)
 	    new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description,
 	    new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description,
 				(*Target)->ShortDesc, ExpectedIndexHash);
 				(*Target)->ShortDesc, ExpectedIndexHash);
-	 else if (transInRelease == false || MetaIndexParser->Exists((*Target)->MetaKey) == true)
+	 else if (transInRelease == false || Record != NULL || compressedAvailable == true)
 	 {
 	 {
 	    if (_config->FindB("Acquire::PDiffs",true) == true && transInRelease == true &&
 	    if (_config->FindB("Acquire::PDiffs",true) == true && transInRelease == true &&
 		MetaIndexParser->Exists(string((*Target)->MetaKey).append(".diff/Index")) == true)
 		MetaIndexParser->Exists(string((*Target)->MetaKey).append(".diff/Index")) == true)
@@ -1526,7 +1556,7 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 	    VerifiedSigFile.append(".gpg");
 	    VerifiedSigFile.append(".gpg");
 	 Rename(LastGoodSigFile, VerifiedSigFile);
 	 Rename(LastGoodSigFile, VerifiedSigFile);
 	 Status = StatTransientNetworkError;
 	 Status = StatTransientNetworkError;
-	 _error->Warning(_("A error occurred during the signature "
+	 _error->Warning(_("An error occurred during the signature "
 			   "verification. The repository is not updated "
 			   "verification. The repository is not updated "
 			   "and the previous index files will be used. "
 			   "and the previous index files will be used. "
 			   "GPG error: %s: %s\n"),
 			   "GPG error: %s: %s\n"),
@@ -1588,14 +1618,25 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner,		/*{{{*/
 
 
    // keep the old InRelease around in case of transistent network errors
    // keep the old InRelease around in case of transistent network errors
    string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
    string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
-   struct stat Buf;
-   if (stat(Final.c_str(),&Buf) == 0)
+   if (RealFileExists(Final) == true)
    {
    {
       string const LastGoodSig = DestFile + ".reverify";
       string const LastGoodSig = DestFile + ".reverify";
       Rename(Final,LastGoodSig);
       Rename(Final,LastGoodSig);
    }
    }
 }
 }
 									/*}}}*/
 									/*}}}*/
+pkgAcqMetaClearSig::~pkgAcqMetaClearSig()				/*{{{*/
+{
+   // if the file was never queued undo file-changes done in the constructor
+   if (QueueCounter == 1 && Status == StatIdle && FileSize == 0 && Complete == false)
+   {
+      string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
+      string const LastGoodSig = DestFile + ".reverify";
+      if (RealFileExists(Final) == false && RealFileExists(LastGoodSig) == true)
+	 Rename(LastGoodSig, Final);
+   }
+}
+									/*}}}*/
 // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers	/*{{{*/
 // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 // FIXME: this can go away once the InRelease file is used widely
 // FIXME: this can go away once the InRelease file is used widely
@@ -1606,7 +1647,11 @@ string pkgAcqMetaClearSig::Custom600Headers()
 
 
    struct stat Buf;
    struct stat Buf;
    if (stat(Final.c_str(),&Buf) != 0)
    if (stat(Final.c_str(),&Buf) != 0)
-      return "\nIndex-File: true\nFail-Ignore: true\n";
+   {
+      Final = DestFile + ".reverify";
+      if (stat(Final.c_str(),&Buf) != 0)
+	 return "\nIndex-File: true\nFail-Ignore: true\n";
+   }
 
 
    return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
    return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
 }

+ 2 - 0
apt-pkg/acquire-item.h

@@ -774,6 +774,7 @@ class pkgAcqMetaSig : public pkgAcquire::Item
 		 std::string MetaIndexURI, std::string MetaIndexURIDesc, std::string MetaIndexShortDesc,
 		 std::string MetaIndexURI, std::string MetaIndexURIDesc, std::string MetaIndexShortDesc,
 		 const std::vector<struct IndexTarget*>* IndexTargets,
 		 const std::vector<struct IndexTarget*>* IndexTargets,
 		 indexRecords* MetaIndexParser);
 		 indexRecords* MetaIndexParser);
+   virtual ~pkgAcqMetaSig();
 };
 };
 									/*}}}*/
 									/*}}}*/
 /** \brief An item that is responsible for downloading the meta-index	{{{
 /** \brief An item that is responsible for downloading the meta-index	{{{
@@ -904,6 +905,7 @@ public:
 		std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc,
 		std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc,
 		const std::vector<struct IndexTarget*>* IndexTargets,
 		const std::vector<struct IndexTarget*>* IndexTargets,
 		indexRecords* MetaIndexParser);
 		indexRecords* MetaIndexParser);
+   virtual ~pkgAcqMetaClearSig();
 };
 };
 									/*}}}*/
 									/*}}}*/
 /** \brief An item that is responsible for fetching a package file.	{{{
 /** \brief An item that is responsible for fetching a package file.	{{{

+ 10 - 3
apt-pkg/acquire-worker.cc

@@ -305,7 +305,15 @@ bool pkgAcquire::Worker::RunMessages()
 	    
 	    
 	    OwnerQ->ItemDone(Itm);
 	    OwnerQ->ItemDone(Itm);
 	    unsigned long long const ServerSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10);
 	    unsigned long long const ServerSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10);
-	    if (TotalSize != 0 && ServerSize != TotalSize)
+            bool isHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) ||
+                         StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false);
+            // Using the https method the server might return 200, but the
+            // If-Modified-Since condition is not satsified, libcurl will
+            // discard the download. In this case, however, TotalSize will be
+            // set to the actual size of the file, while ServerSize will be set
+            // to 0. Therefore, if the item is marked as a hit and the
+            // downloaded size (ServerSize) is 0, we ignore TotalSize.
+	    if (TotalSize != 0 && (!isHit || ServerSize != 0) && ServerSize != TotalSize)
 	       _error->Warning("Size of file %s is not what the server reported %s %llu",
 	       _error->Warning("Size of file %s is not what the server reported %s %llu",
 			       Owner->DestFile.c_str(), LookupTag(Message,"Size","0").c_str(),TotalSize);
 			       Owner->DestFile.c_str(), LookupTag(Message,"Size","0").c_str(),TotalSize);
 
 
@@ -332,8 +340,7 @@ bool pkgAcquire::Worker::RunMessages()
 	    // Log that we are done
 	    // Log that we are done
 	    if (Log != 0)
 	    if (Log != 0)
 	    {
 	    {
-	       if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true ||
-		   StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
+	       if (isHit)
 	       {
 	       {
 		  /* Hide 'hits' for local only sources - we also manage to
 		  /* Hide 'hits' for local only sources - we also manage to
 		     hide gets */
 		     hide gets */

+ 16 - 7
apt-pkg/algorithms.cc

@@ -646,7 +646,10 @@ void pkgProblemResolver::MakeScores()
 	      D->Type != pkgCache::Dep::Recommends))
 	      D->Type != pkgCache::Dep::Recommends))
 	    continue;	 
 	    continue;	 
 	 
 	 
-	 Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]);
+	 // Do not propagate negative scores otherwise
+	 // an extra (-2) package might score better than an optional (-1)
+	 if (OldScores[D.ParentPkg()->ID] > 0)
+	     Scores[I->ID] += OldScores[D.ParentPkg()->ID];
       }      
       }      
    }
    }
 
 
@@ -840,8 +843,10 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
    }
    }
    while (Again == true);
    while (Again == true);
 
 
-   if (Debug == true)
-      clog << "Starting" << endl;
+   if (Debug == true) {
+      clog << "Starting pkgProblemResolver with broken count: " 
+           << Cache.BrokenCount() << endl;
+   }
    
    
    MakeScores();
    MakeScores();
 
 
@@ -869,8 +874,10 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
          }
          }
    }
    }
 
 
-   if (Debug == true)
-      clog << "Starting 2" << endl;
+   if (Debug == true) {
+      clog << "Starting 2 pkgProblemResolver with broken count: " 
+           << Cache.BrokenCount() << endl;
+   }
 
 
    /* Now consider all broken packages. For each broken package we either
    /* Now consider all broken packages. For each broken package we either
       remove the package or fix it's problem. We do this once, it should
       remove the package or fix it's problem. We do this once, it should
@@ -1435,9 +1442,11 @@ bool pkgProblemResolver::ResolveByKeepInternal()
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// ProblemResolver::InstallProtect - Install all protected packages	/*{{{*/
+// ProblemResolver::InstallProtect - deprecated cpu-eating no-op	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* This is used to make sure protected packages are installed */
+/* Actions issued with FromUser bit set are protected from further
+   modification (expect by other calls with FromUser set) nowadays , so we
+   don't need to reissue actions here, they are already set in stone. */
 void pkgProblemResolver::InstallProtect()
 void pkgProblemResolver::InstallProtect()
 {
 {
    pkgDepCache::ActionGroup group(Cache);
    pkgDepCache::ActionGroup group(Cache);

+ 4 - 3
apt-pkg/algorithms.h

@@ -36,6 +36,8 @@
 
 
 #include <iostream>
 #include <iostream>
 
 
+#include <apt-pkg/macros.h>
+
 #ifndef APT_8_CLEANER_HEADERS
 #ifndef APT_8_CLEANER_HEADERS
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire.h>
 using std::ostream;
 using std::ostream;
@@ -132,9 +134,8 @@ class pkgProblemResolver						/*{{{*/
    // Try to resolve problems only by using keep
    // Try to resolve problems only by using keep
    bool ResolveByKeep();
    bool ResolveByKeep();
 
 
-   // Install all protected packages   
-   void InstallProtect();   
-   
+   __deprecated void InstallProtect();
+
    pkgProblemResolver(pkgDepCache *Cache);
    pkgProblemResolver(pkgDepCache *Cache);
    ~pkgProblemResolver();
    ~pkgProblemResolver();
 };
 };

+ 2 - 2
apt-pkg/aptconfiguration.cc

@@ -388,12 +388,12 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
 		if (dpkgMultiArch == 0) {
 		if (dpkgMultiArch == 0) {
 			close(external[0]);
 			close(external[0]);
 			std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory");
 			std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory");
-			if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0)
-				_error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --print-foreign-architectures", chrootDir.c_str());
 			int const nullfd = open("/dev/null", O_RDONLY);
 			int const nullfd = open("/dev/null", O_RDONLY);
 			dup2(nullfd, STDIN_FILENO);
 			dup2(nullfd, STDIN_FILENO);
 			dup2(external[1], STDOUT_FILENO);
 			dup2(external[1], STDOUT_FILENO);
 			dup2(nullfd, STDERR_FILENO);
 			dup2(nullfd, STDERR_FILENO);
+			if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0)
+				_error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --print-foreign-architectures", chrootDir.c_str());
 			execvp(Args[0], (char**) &Args[0]);
 			execvp(Args[0], (char**) &Args[0]);
 			_error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!");
 			_error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!");
 			_exit(100);
 			_exit(100);

+ 1 - 0
apt-pkg/cacheiterators.h

@@ -220,6 +220,7 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
 	inline VerFileIterator FileList() const;
 	inline VerFileIterator FileList() const;
 	bool Downloadable() const;
 	bool Downloadable() const;
 	inline const char *PriorityType() const {return Owner->Priority(S->Priority);};
 	inline const char *PriorityType() const {return Owner->Priority(S->Priority);};
+	const char *MultiArchType() const;
 	std::string RelStr() const;
 	std::string RelStr() const;
 
 
 	bool Automatic() const;
 	bool Automatic() const;

+ 0 - 1
apt-pkg/cacheset.h

@@ -11,7 +11,6 @@
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
 #include <iostream>
 #include <iostream>
 #include <fstream>
 #include <fstream>
-#include <list>
 #include <map>
 #include <map>
 #include <set>
 #include <set>
 #include <list>
 #include <list>

+ 8 - 0
apt-pkg/cdrom.cc

@@ -829,6 +829,14 @@ bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
       log->Update(msg.str());
       log->Update(msg.str());
       log->Update(_("Copying package lists..."), STEP_COPY);
       log->Update(_("Copying package lists..."), STEP_COPY);
    }
    }
+
+   // check for existence and possibly create state directory for copying
+   string const listDir = _config->FindDir("Dir::State::lists");
+   string const partialListDir = listDir + "partial/";
+   if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false &&
+       CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false)
+      return _error->Errno("cdrom", _("List directory %spartial is missing."), listDir.c_str());
+
    // take care of the signatures and copy them if they are ok
    // take care of the signatures and copy them if they are ok
    // (we do this before PackageCopy as it modifies "List" and "SourceList")
    // (we do this before PackageCopy as it modifies "List" and "SourceList")
    SigVerify SignVerify;
    SigVerify SignVerify;

+ 1 - 1
apt-pkg/cdrom.h

@@ -18,7 +18,7 @@ class pkgCdromStatus							/*{{{*/
    int totalSteps;
    int totalSteps;
 
 
  public:
  public:
-   pkgCdromStatus() {};
+   pkgCdromStatus() : totalSteps(0) {};
    virtual ~pkgCdromStatus() {};
    virtual ~pkgCdromStatus() {};
 
 
    // total steps
    // total steps

+ 2 - 1
apt-pkg/contrib/cdromutl.cc

@@ -122,8 +122,9 @@ bool MountCdrom(string Path, string DeviceName)
    if (Child == 0)
    if (Child == 0)
    {
    {
       // Make all the fds /dev/null
       // Make all the fds /dev/null
+      int null_fd = open("/dev/null",O_RDWR);
       for (int I = 0; I != 3; I++)
       for (int I = 0; I != 3; I++)
-	 dup2(open("/dev/null",O_RDWR),I);
+	 dup2(null_fd, I);
       
       
       if (_config->Exists("Acquire::cdrom::"+Path+"::Mount") == true)
       if (_config->Exists("Acquire::cdrom::"+Path+"::Mount") == true)
       {
       {

+ 1 - 1
apt-pkg/contrib/configuration.cc

@@ -823,7 +823,7 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio
 	    // Go down a level
 	    // Go down a level
 	    if (TermChar == '{')
 	    if (TermChar == '{')
 	    {
 	    {
-	       if (StackPos <= 100)
+	       if (StackPos < sizeof(Stack)/sizeof(std::string))
 		  Stack[StackPos++] = ParentTag;
 		  Stack[StackPos++] = ParentTag;
 	       
 	       
 	       /* Make sectional tags incorperate the section into the
 	       /* Make sectional tags incorperate the section into the

+ 6 - 4
apt-pkg/contrib/error.cc

@@ -67,9 +67,10 @@ bool GlobalError::NAME (const char *Function, const char *Description,...) { \
 	int const errsv = errno; \
 	int const errsv = errno; \
 	while (true) { \
 	while (true) { \
 		va_start(args,Description); \
 		va_start(args,Description); \
-		if (InsertErrno(TYPE, Function, Description, args, errsv, msgSize) == false) \
-			break; \
+		bool const retry = InsertErrno(TYPE, Function, Description, args, errsv, msgSize); \
 		va_end(args); \
 		va_end(args); \
+		if (retry == false) \
+			break; \
 	} \
 	} \
 	return false; \
 	return false; \
 }
 }
@@ -88,9 +89,10 @@ bool GlobalError::InsertErrno(MsgType const &type, const char *Function,
 	int const errsv = errno;
 	int const errsv = errno;
 	while (true) {
 	while (true) {
 		va_start(args,Description);
 		va_start(args,Description);
-		if (InsertErrno(type, Function, Description, args, errsv, msgSize) == false)
-			break;
+		bool const retry = InsertErrno(type, Function, Description, args, errsv, msgSize);
 		va_end(args);
 		va_end(args);
+		if (retry == false)
+		   break;
 	}
 	}
 	return false;
 	return false;
 }
 }

+ 35 - 6
apt-pkg/contrib/error.h

@@ -123,6 +123,25 @@ public:									/*{{{*/
 	bool InsertErrno(MsgType const &type, const char* Function,
 	bool InsertErrno(MsgType const &type, const char* Function,
 			 const char* Description,...) __like_printf(4) __cold;
 			 const char* Description,...) __like_printf(4) __cold;
 
 
+	/** \brief adds an errno message with the given type
+	 *
+	 * args needs to be initialized with va_start and terminated
+	 * with va_end by the caller. msgSize is also an out-parameter
+	 * in case the msgSize was not enough to store the complete message.
+	 *
+	 * \param type of the error message
+	 * \param Function which failed
+	 * \param Description is the format string for args
+	 * \param args list from a printf-like function
+	 * \param errsv is the errno the error is for
+	 * \param msgSize is the size of the char[] used to store message
+	 * \return true if the message was added, false if not - the caller
+	 * should call this method again in that case
+	 */
+	bool InsertErrno(MsgType type, const char* Function,
+			 const char* Description, va_list &args,
+			 int const errsv, size_t &msgSize);
+
 	/** \brief add an fatal error message to the list
 	/** \brief add an fatal error message to the list
 	 *
 	 *
 	 *  Most of the stuff we consider as "error" is also "fatal" for
 	 *  Most of the stuff we consider as "error" is also "fatal" for
@@ -185,6 +204,22 @@ public:									/*{{{*/
 	 */
 	 */
 	bool Insert(MsgType const &type, const char* Description,...) __like_printf(3) __cold;
 	bool Insert(MsgType const &type, const char* Description,...) __like_printf(3) __cold;
 
 
+	/** \brief adds an error message with the given type
+	 *
+	 * args needs to be initialized with va_start and terminated
+	 * with va_end by the caller. msgSize is also an out-parameter
+	 * in case the msgSize was not enough to store the complete message.
+	 *
+	 * \param type of the error message
+	 * \param Description is the format string for args
+	 * \param args list from a printf-like function
+	 * \param msgSize is the size of the char[] used to store message
+	 * \return true if the message was added, false if not - the caller
+	 * should call this method again in that case
+	 */
+	bool Insert(MsgType type, const char* Description,
+			 va_list &args, size_t &msgSize) __cold;
+
 	/** \brief is an error in the list?
 	/** \brief is an error in the list?
 	 *
 	 *
 	 *  \return \b true if an error is included in the list, \b false otherwise
 	 *  \return \b true if an error is included in the list, \b false otherwise
@@ -305,12 +340,6 @@ private:								/*{{{*/
 	};
 	};
 
 
 	std::list<MsgStack> Stacks;
 	std::list<MsgStack> Stacks;
-
-	bool InsertErrno(MsgType type, const char* Function,
-			 const char* Description, va_list &args,
-			 int const errsv, size_t &msgSize);
-	bool Insert(MsgType type, const char* Description,
-			 va_list &args, size_t &msgSize);
 									/*}}}*/
 									/*}}}*/
 };
 };
 									/*}}}*/
 									/*}}}*/

+ 114 - 106
apt-pkg/contrib/fileutl.cc

@@ -186,7 +186,8 @@ bool RunScripts(const char *Cnf)
 /* The caller is expected to set things so that failure causes erasure */
 /* The caller is expected to set things so that failure causes erasure */
 bool CopyFile(FileFd &From,FileFd &To)
 bool CopyFile(FileFd &From,FileFd &To)
 {
 {
-   if (From.IsOpen() == false || To.IsOpen() == false)
+   if (From.IsOpen() == false || To.IsOpen() == false ||
+	 From.Failed() == true || To.Failed() == true)
       return false;
       return false;
    
    
    // Buffered copy between fds
    // Buffered copy between fds
@@ -245,17 +246,20 @@ int GetLock(string File,bool Errors)
    fl.l_len = 0;
    fl.l_len = 0;
    if (fcntl(FD,F_SETLK,&fl) == -1)
    if (fcntl(FD,F_SETLK,&fl) == -1)
    {
    {
+      // always close to not leak resources
+      int Tmp = errno;
+      close(FD);
+      errno = Tmp;
+
       if (errno == ENOLCK)
       if (errno == ENOLCK)
       {
       {
 	 _error->Warning(_("Not using locking for nfs mounted lock file %s"),File.c_str());
 	 _error->Warning(_("Not using locking for nfs mounted lock file %s"),File.c_str());
 	 return dup(0);       // Need something for the caller to close	 
 	 return dup(0);       // Need something for the caller to close	 
-      }      
+      }
+  
       if (Errors == true)
       if (Errors == true)
 	 _error->Errno("open",_("Could not get lock %s"),File.c_str());
 	 _error->Errno("open",_("Could not get lock %s"),File.c_str());
       
       
-      int Tmp = errno;
-      close(FD);
-      errno = Tmp;
       return -1;
       return -1;
    }
    }
 
 
@@ -883,7 +887,7 @@ bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress,
       return Open(FileName, ReadOnly, Gzip, Perms);
       return Open(FileName, ReadOnly, Gzip, Perms);
 
 
    if (Compress == Auto && (Mode & WriteOnly) == WriteOnly)
    if (Compress == Auto && (Mode & WriteOnly) == WriteOnly)
-      return _error->Error("Autodetection on %s only works in ReadOnly openmode!", FileName.c_str());
+      return FileFdError("Autodetection on %s only works in ReadOnly openmode!", FileName.c_str());
 
 
    std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
    std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
    std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin();
    std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin();
@@ -936,17 +940,17 @@ bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress,
       case Auto:
       case Auto:
       case Extension:
       case Extension:
 	 // Unreachable
 	 // Unreachable
-	 return _error->Error("Opening File %s in None, Auto or Extension should be already handled?!?", FileName.c_str());
+	 return FileFdError("Opening File %s in None, Auto or Extension should be already handled?!?", FileName.c_str());
       }
       }
       for (; compressor != compressors.end(); ++compressor)
       for (; compressor != compressors.end(); ++compressor)
 	 if (compressor->Name == name)
 	 if (compressor->Name == name)
 	    break;
 	    break;
       if (compressor == compressors.end())
       if (compressor == compressors.end())
-	 return _error->Error("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str());
+	 return FileFdError("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str());
    }
    }
 
 
    if (compressor == compressors.end())
    if (compressor == compressors.end())
-      return _error->Error("Can't find a match for specified compressor mode for file %s", FileName.c_str());
+      return FileFdError("Can't find a match for specified compressor mode for file %s", FileName.c_str());
    return Open(FileName, Mode, *compressor, Perms);
    return Open(FileName, Mode, *compressor, Perms);
 }
 }
 bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor, unsigned long const Perms)
 bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor, unsigned long const Perms)
@@ -955,9 +959,9 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co
    Flags = AutoClose;
    Flags = AutoClose;
 
 
    if ((Mode & WriteOnly) != WriteOnly && (Mode & (Atomic | Create | Empty | Exclusive)) != 0)
    if ((Mode & WriteOnly) != WriteOnly && (Mode & (Atomic | Create | Empty | Exclusive)) != 0)
-      return _error->Error("ReadOnly mode for %s doesn't accept additional flags!", FileName.c_str());
+      return FileFdError("ReadOnly mode for %s doesn't accept additional flags!", FileName.c_str());
    if ((Mode & ReadWrite) == 0)
    if ((Mode & ReadWrite) == 0)
-      return _error->Error("No openmode provided in FileFd::Open for %s", FileName.c_str());
+      return FileFdError("No openmode provided in FileFd::Open for %s", FileName.c_str());
 
 
    if ((Mode & Atomic) == Atomic)
    if ((Mode & Atomic) == Atomic)
    {
    {
@@ -1003,7 +1007,7 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co
 	 close (iFd);
 	 close (iFd);
 	 iFd = -1;
 	 iFd = -1;
       }
       }
-      return _error->Errno("open",_("Could not open file %s"), FileName.c_str());
+      return FileFdErrno("open",_("Could not open file %s"), FileName.c_str());
    }
    }
 
 
    SetCloseExec(iFd,true);
    SetCloseExec(iFd,true);
@@ -1032,14 +1036,19 @@ bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compre
    case Xz: name = "xz"; break;
    case Xz: name = "xz"; break;
    case Auto:
    case Auto:
    case Extension:
    case Extension:
-      return _error->Error("Opening Fd %d in Auto or Extension compression mode is not supported", Fd);
+      if (AutoClose == true && Fd != -1)
+	 close(Fd);
+      return FileFdError("Opening Fd %d in Auto or Extension compression mode is not supported", Fd);
    }
    }
    for (; compressor != compressors.end(); ++compressor)
    for (; compressor != compressors.end(); ++compressor)
       if (compressor->Name == name)
       if (compressor->Name == name)
 	 break;
 	 break;
    if (compressor == compressors.end())
    if (compressor == compressors.end())
-      return _error->Error("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str());
-
+   {
+      if (AutoClose == true && Fd != -1)
+	 close(Fd);
+      return FileFdError("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str());
+   }
    return OpenDescriptor(Fd, Mode, *compressor, AutoClose);
    return OpenDescriptor(Fd, Mode, *compressor, AutoClose);
 }
 }
 bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose)
 bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose)
@@ -1061,11 +1070,21 @@ bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration:
    else
    else
       iFd = Fd;
       iFd = Fd;
    this->FileName = "";
    this->FileName = "";
-   if (OpenInternDescriptor(Mode, compressor) == false)
+   if (Fd == -1 || OpenInternDescriptor(Mode, compressor) == false)
    {
    {
-      if (AutoClose)
+      if (iFd != -1 && (
+#ifdef HAVE_ZLIB
+	compressor.Name == "gzip" ||
+#endif
+#ifdef HAVE_BZ2
+	compressor.Name == "bzip2" ||
+#endif
+	AutoClose == true))
+      {
 	 close (iFd);
 	 close (iFd);
-      return _error->Errno("gzdopen",_("Could not open file descriptor %d"), Fd);
+	 iFd = -1;
+      }
+      return FileFdError(_("Could not open file descriptor %d"), Fd);
    }
    }
    return true;
    return true;
 }
 }
@@ -1127,10 +1146,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
       ExecWait(d->compressor_pid, "FileFdCompressor", true);
       ExecWait(d->compressor_pid, "FileFdCompressor", true);
 
 
    if ((Mode & ReadWrite) == ReadWrite)
    if ((Mode & ReadWrite) == ReadWrite)
-   {
-      Flags |= Fail;
-      return _error->Error("ReadWrite mode is not supported for file %s", FileName.c_str());
-   }
+      return FileFdError("ReadWrite mode is not supported for file %s", FileName.c_str());
 
 
    bool const Comp = (Mode & WriteOnly) == WriteOnly;
    bool const Comp = (Mode & WriteOnly) == WriteOnly;
    if (Comp == false)
    if (Comp == false)
@@ -1153,10 +1169,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C
    // Create a data pipe
    // Create a data pipe
    int Pipe[2] = {-1,-1};
    int Pipe[2] = {-1,-1};
    if (pipe(Pipe) != 0)
    if (pipe(Pipe) != 0)
-   {
-      Flags |= Fail;
-      return _error->Errno("pipe",_("Failed to create subprocess IPC"));
-   }
+      return FileFdErrno("pipe",_("Failed to create subprocess IPC"));
    for (int J = 0; J != 2; J++)
    for (int J = 0; J != 2; J++)
       SetCloseExec(Pipe[J],true);
       SetCloseExec(Pipe[J],true);
 
 
@@ -1230,11 +1243,9 @@ FileFd::~FileFd()
 {
 {
    Close();
    Close();
    if (d != NULL)
    if (d != NULL)
-   {
       d->CloseDown(FileName);
       d->CloseDown(FileName);
-      delete d;
-      d = NULL;
-   }
+   delete d;
+   d = NULL;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // FileFd::Read - Read a bit of the file				/*{{{*/
 // FileFd::Read - Read a bit of the file				/*{{{*/
@@ -1266,14 +1277,13 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
       {
       {
 	 if (errno == EINTR)
 	 if (errno == EINTR)
 	    continue;
 	    continue;
-	 Flags |= Fail;
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
 	 if (d != NULL && d->gz != NULL)
 	 if (d != NULL && d->gz != NULL)
 	 {
 	 {
 	    int err;
 	    int err;
 	    char const * const errmsg = gzerror(d->gz, &err);
 	    char const * const errmsg = gzerror(d->gz, &err);
 	    if (err != Z_ERRNO)
 	    if (err != Z_ERRNO)
-	       return _error->Error("gzread: %s (%d: %s)", _("Read error"), err, errmsg);
+	       return FileFdError("gzread: %s (%d: %s)", _("Read error"), err, errmsg);
 	 }
 	 }
 #endif
 #endif
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
@@ -1282,10 +1292,10 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
 	    int err;
 	    int err;
 	    char const * const errmsg = BZ2_bzerror(d->bz2, &err);
 	    char const * const errmsg = BZ2_bzerror(d->bz2, &err);
 	    if (err != BZ_IO_ERROR)
 	    if (err != BZ_IO_ERROR)
-	       return _error->Error("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg);
+	       return FileFdError("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg);
 	 }
 	 }
 #endif
 #endif
-	 return _error->Errno("read",_("Read error"));
+	 return FileFdErrno("read",_("Read error"));
       }
       }
       
       
       To = (char *)To + Res;
       To = (char *)To + Res;
@@ -1306,9 +1316,8 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
       Flags |= HitEof;
       Flags |= HitEof;
       return true;
       return true;
    }
    }
-   
-   Flags |= Fail;
-   return _error->Error(_("read, still have %llu to read but none left"), Size);
+
+   return FileFdError(_("read, still have %llu to read but none left"), Size);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // FileFd::ReadLine - Read a complete line from the file		/*{{{*/
 // FileFd::ReadLine - Read a complete line from the file		/*{{{*/
@@ -1364,14 +1373,13 @@ bool FileFd::Write(const void *From,unsigned long long Size)
 	 continue;
 	 continue;
       if (Res < 0)
       if (Res < 0)
       {
       {
-	 Flags |= Fail;
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
 	 if (d != NULL && d->gz != NULL)
 	 if (d != NULL && d->gz != NULL)
 	 {
 	 {
 	    int err;
 	    int err;
 	    char const * const errmsg = gzerror(d->gz, &err);
 	    char const * const errmsg = gzerror(d->gz, &err);
 	    if (err != Z_ERRNO)
 	    if (err != Z_ERRNO)
-	       return _error->Error("gzwrite: %s (%d: %s)", _("Write error"), err, errmsg);
+	       return FileFdError("gzwrite: %s (%d: %s)", _("Write error"), err, errmsg);
 	 }
 	 }
 #endif
 #endif
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
@@ -1380,10 +1388,10 @@ bool FileFd::Write(const void *From,unsigned long long Size)
 	    int err;
 	    int err;
 	    char const * const errmsg = BZ2_bzerror(d->bz2, &err);
 	    char const * const errmsg = BZ2_bzerror(d->bz2, &err);
 	    if (err != BZ_IO_ERROR)
 	    if (err != BZ_IO_ERROR)
-	       return _error->Error("BZ2_bzwrite: %s (%d: %s)", _("Write error"), err, errmsg);
+	       return FileFdError("BZ2_bzwrite: %s (%d: %s)", _("Write error"), err, errmsg);
 	 }
 	 }
 #endif
 #endif
-	 return _error->Errno("write",_("Write error"));
+	 return FileFdErrno("write",_("Write error"));
       }
       }
       
       
       From = (char *)From + Res;
       From = (char *)From + Res;
@@ -1395,9 +1403,8 @@ bool FileFd::Write(const void *From,unsigned long long Size)
    
    
    if (Size == 0)
    if (Size == 0)
       return true;
       return true;
-   
-   Flags |= Fail;
-   return _error->Error(_("write, still have %llu to write but couldn't"), Size);
+
+   return FileFdError(_("write, still have %llu to write but couldn't"), Size);
 }
 }
 bool FileFd::Write(int Fd, const void *From, unsigned long long Size)
 bool FileFd::Write(int Fd, const void *From, unsigned long long Size)
 {
 {
@@ -1441,13 +1448,13 @@ bool FileFd::Seek(unsigned long long To)
 	 return Skip(To - seekpos);
 	 return Skip(To - seekpos);
 
 
       if ((d->openmode & ReadOnly) != ReadOnly)
       if ((d->openmode & ReadOnly) != ReadOnly)
-      {
-	 Flags |= Fail;
-	 return _error->Error("Reopen is only implemented for read-only files!");
-      }
+	 return FileFdError("Reopen is only implemented for read-only files!");
 #ifdef HAVE_BZ2
 #ifdef HAVE_BZ2
-      if (d->bz2 != NULL)
-	 BZ2_bzclose(d->bz2);
+     if (d->bz2 != NULL) 
+     {
+	BZ2_bzclose(d->bz2);
+	d->bz2 = NULL;
+     }
 #endif
 #endif
       if (iFd != -1)
       if (iFd != -1)
 	 close(iFd);
 	 close(iFd);
@@ -1462,17 +1469,11 @@ bool FileFd::Seek(unsigned long long To)
 	    if (lseek(d->compressed_fd, 0, SEEK_SET) != 0)
 	    if (lseek(d->compressed_fd, 0, SEEK_SET) != 0)
 	       iFd = d->compressed_fd;
 	       iFd = d->compressed_fd;
 	 if (iFd < 0)
 	 if (iFd < 0)
-	 {
-	    Flags |= Fail;
-	    return _error->Error("Reopen is not implemented for pipes opened with FileFd::OpenDescriptor()!");
-	 }
+	    return FileFdError("Reopen is not implemented for pipes opened with FileFd::OpenDescriptor()!");
       }
       }
 
 
       if (OpenInternDescriptor(d->openmode, d->compressor) == false)
       if (OpenInternDescriptor(d->openmode, d->compressor) == false)
-      {
-	 Flags |= Fail;
-	 return _error->Error("Seek on file %s because it couldn't be reopened", FileName.c_str());
-      }
+	 return FileFdError("Seek on file %s because it couldn't be reopened", FileName.c_str());
 
 
       if (To != 0)
       if (To != 0)
 	 return Skip(To);
 	 return Skip(To);
@@ -1488,10 +1489,7 @@ bool FileFd::Seek(unsigned long long To)
 #endif
 #endif
       res = lseek(iFd,To,SEEK_SET);
       res = lseek(iFd,To,SEEK_SET);
    if (res != (signed)To)
    if (res != (signed)To)
-   {
-      Flags |= Fail;
-      return _error->Error("Unable to seek to %llu", To);
-   }
+      return FileFdError("Unable to seek to %llu", To);
 
 
    if (d != NULL)
    if (d != NULL)
       d->seekpos = To;
       d->seekpos = To;
@@ -1515,10 +1513,7 @@ bool FileFd::Skip(unsigned long long Over)
       {
       {
 	 unsigned long long toread = std::min((unsigned long long) sizeof(buffer), Over);
 	 unsigned long long toread = std::min((unsigned long long) sizeof(buffer), Over);
 	 if (Read(buffer, toread) == false)
 	 if (Read(buffer, toread) == false)
-	 {
-	    Flags |= Fail;
-	    return _error->Error("Unable to seek ahead %llu",Over);
-	 }
+	    return FileFdError("Unable to seek ahead %llu",Over);
 	 Over -= toread;
 	 Over -= toread;
       }
       }
       return true;
       return true;
@@ -1532,10 +1527,7 @@ bool FileFd::Skip(unsigned long long Over)
 #endif
 #endif
       res = lseek(iFd,Over,SEEK_CUR);
       res = lseek(iFd,Over,SEEK_CUR);
    if (res < 0)
    if (res < 0)
-   {
-      Flags |= Fail;
-      return _error->Error("Unable to seek ahead %llu",Over);
-   }
+      return FileFdError("Unable to seek ahead %llu",Over);
    if (d != NULL)
    if (d != NULL)
       d->seekpos = res;
       d->seekpos = res;
 
 
@@ -1549,17 +1541,11 @@ bool FileFd::Truncate(unsigned long long To)
 {
 {
 #if defined HAVE_ZLIB || defined HAVE_BZ2
 #if defined HAVE_ZLIB || defined HAVE_BZ2
    if (d != NULL && (d->gz != NULL || d->bz2 != NULL))
    if (d != NULL && (d->gz != NULL || d->bz2 != NULL))
-   {
-      Flags |= Fail;
-      return _error->Error("Truncating compressed files is not implemented (%s)", FileName.c_str());
-   }
+      return FileFdError("Truncating compressed files is not implemented (%s)", FileName.c_str());
 #endif
 #endif
    if (ftruncate(iFd,To) != 0)
    if (ftruncate(iFd,To) != 0)
-   {
-      Flags |= Fail;
-      return _error->Error("Unable to truncate to %llu",To);
-   }
-   
+      return FileFdError("Unable to truncate to %llu",To);
+
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1587,10 +1573,7 @@ unsigned long long FileFd::Tell()
 #endif
 #endif
      Res = lseek(iFd,0,SEEK_CUR);
      Res = lseek(iFd,0,SEEK_CUR);
    if (Res == (off_t)-1)
    if (Res == (off_t)-1)
-   {
-      Flags |= Fail;
-      _error->Errno("lseek","Failed to determine the current file position");
-   }
+      FileFdErrno("lseek","Failed to determine the current file position");
    if (d != NULL)
    if (d != NULL)
       d->seekpos = Res;
       d->seekpos = Res;
    return Res;
    return Res;
@@ -1603,10 +1586,7 @@ unsigned long long FileFd::FileSize()
 {
 {
    struct stat Buf;
    struct stat Buf;
    if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0)
    if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0)
-   {
-      Flags |= Fail;
-      return _error->Errno("fstat","Unable to determine the file size");
-   }
+      return FileFdErrno("fstat","Unable to determine the file size");
 
 
    // for compressor pipes st_size is undefined and at 'best' zero
    // for compressor pipes st_size is undefined and at 'best' zero
    if ((d != NULL && d->pipe == true) || S_ISFIFO(Buf.st_mode))
    if ((d != NULL && d->pipe == true) || S_ISFIFO(Buf.st_mode))
@@ -1616,10 +1596,7 @@ unsigned long long FileFd::FileSize()
       if (d != NULL)
       if (d != NULL)
 	 d->pipe = true;
 	 d->pipe = true;
       if (stat(FileName.c_str(), &Buf) != 0)
       if (stat(FileName.c_str(), &Buf) != 0)
-      {
-	 Flags |= Fail;
-	 return _error->Errno("stat","Unable to determine the file size");
-      }
+	 return FileFdErrno("stat","Unable to determine the file size");
    }
    }
 
 
    return Buf.st_size;
    return Buf.st_size;
@@ -1644,7 +1621,11 @@ unsigned long long FileFd::Size()
       char ignore[1000];
       char ignore[1000];
       unsigned long long read = 0;
       unsigned long long read = 0;
       do {
       do {
-	 Read(ignore, sizeof(ignore), &read);
+	 if (Read(ignore, sizeof(ignore), &read) == false)
+	 {
+	    Seek(oldSeek);
+	    return 0;
+	 }
       } while(read != 0);
       } while(read != 0);
       size = Tell();
       size = Tell();
       Seek(oldSeek);
       Seek(oldSeek);
@@ -1662,14 +1643,14 @@ unsigned long long FileFd::Size()
        // FIXME: Size for gz-files is limited by 32bit… no largefile support
        // FIXME: Size for gz-files is limited by 32bit… no largefile support
        if (lseek(iFd, -4, SEEK_END) < 0)
        if (lseek(iFd, -4, SEEK_END) < 0)
        {
        {
-	  Flags |= Fail;
-	  return _error->Errno("lseek","Unable to seek to end of gzipped file");
+	  FileFdErrno("lseek","Unable to seek to end of gzipped file");
+	  return 0;
        }
        }
-       size = 0L;
+       size = 0;
        if (read(iFd, &size, 4) != 4)
        if (read(iFd, &size, 4) != 4)
        {
        {
-	  Flags |= Fail;
-	  return _error->Errno("read","Unable to read original size of gzipped file");
+	  FileFdErrno("read","Unable to read original size of gzipped file");
+	  return 0;
        }
        }
 
 
 #ifdef WORDS_BIGENDIAN
 #ifdef WORDS_BIGENDIAN
@@ -1681,8 +1662,8 @@ unsigned long long FileFd::Size()
 
 
        if (lseek(iFd, oldPos, SEEK_SET) < 0)
        if (lseek(iFd, oldPos, SEEK_SET) < 0)
        {
        {
-	  Flags |= Fail;
-	  return _error->Errno("lseek","Unable to seek in gzipped file");
+	  FileFdErrno("lseek","Unable to seek in gzipped file");
+	  return 0;
        }
        }
 
 
        return size;
        return size;
@@ -1700,8 +1681,7 @@ time_t FileFd::ModificationTime()
    struct stat Buf;
    struct stat Buf;
    if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0)
    if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0)
    {
    {
-      Flags |= Fail;
-      _error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
+      FileFdErrno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
       return 0;
       return 0;
    }
    }
 
 
@@ -1714,8 +1694,7 @@ time_t FileFd::ModificationTime()
 	 d->pipe = true;
 	 d->pipe = true;
       if (stat(FileName.c_str(), &Buf) != 0)
       if (stat(FileName.c_str(), &Buf) != 0)
       {
       {
-	 Flags |= Fail;
-	 _error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
+	 FileFdErrno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
 	 return 0;
 	 return 0;
       }
       }
    }
    }
@@ -1771,11 +1750,40 @@ bool FileFd::Close()
 bool FileFd::Sync()
 bool FileFd::Sync()
 {
 {
    if (fsync(iFd) != 0)
    if (fsync(iFd) != 0)
+      return FileFdErrno("sync",_("Problem syncing the file"));
+   return true;
+}
+									/*}}}*/
+// FileFd::FileFdErrno - set Fail and call _error->Errno		*{{{*/
+bool FileFd::FileFdErrno(const char *Function, const char *Description,...)
+{
+   Flags |= Fail;
+   va_list args;
+   size_t msgSize = 400;
+   int const errsv = errno;
+   while (true)
    {
    {
-      Flags |= Fail;
-      return _error->Errno("sync",_("Problem syncing the file"));
+      va_start(args,Description);
+      if (_error->InsertErrno(GlobalError::ERROR, Function, Description, args, errsv, msgSize) == false)
+	 break;
+      va_end(args);
    }
    }
-   return true;
+   return false;
+}
+									/*}}}*/
+// FileFd::FileFdError - set Fail and call _error->Error		*{{{*/
+bool FileFd::FileFdError(const char *Description,...) {
+   Flags |= Fail;
+   va_list args;
+   size_t msgSize = 400;
+   while (true)
+   {
+      va_start(args,Description);
+      if (_error->Insert(GlobalError::ERROR, Description, args, msgSize) == false)
+	 break;
+      va_end(args);
+   }
+   return false;
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 

+ 4 - 0
apt-pkg/contrib/fileutl.h

@@ -149,6 +149,10 @@ class FileFd
    private:
    private:
    FileFdPrivate* d;
    FileFdPrivate* d;
    bool OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor);
    bool OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor);
+
+   // private helpers to set Fail flag and call _error->Error
+   bool FileFdErrno(const char* Function, const char* Description,...) __like_printf(3) __cold;
+   bool FileFdError(const char* Description,...) __like_printf(2) __cold;
 };
 };
 
 
 bool RunScripts(const char *Cnf);
 bool RunScripts(const char *Cnf);

+ 1 - 1
apt-pkg/contrib/gpgv.cc

@@ -154,7 +154,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
 	 if (sigFd != -1)
 	 if (sigFd != -1)
 	    unlink(data);
 	    unlink(data);
 	 ioprintf(std::cerr, "Splitting up %s into data and signature failed", File.c_str());
 	 ioprintf(std::cerr, "Splitting up %s into data and signature failed", File.c_str());
-	 exit(EINTERNAL);
+	 exit(112);
       }
       }
       Args.push_back(sig);
       Args.push_back(sig);
       Args.push_back(data);
       Args.push_back(data);

+ 12 - 3
apt-pkg/contrib/gpgv.h

@@ -23,9 +23,18 @@
 /** \brief generates and run the command to verify a file with gpgv
 /** \brief generates and run the command to verify a file with gpgv
  *
  *
  * If File and FileSig specify the same file it is assumed that we
  * If File and FileSig specify the same file it is assumed that we
- * deal with a clear-signed message. In that case the file will be
- * rewritten to be in a good-known format without uneeded whitespaces
- * and additional messages (unsigned or signed).
+ * deal with a clear-signed message. Note that the method will accept
+ * and validate files which include additional (unsigned) messages
+ * without complaining. Do NOT open files accepted by this method
+ * for reading. Use #OpenMaybeClearSignedFile to access the message
+ * instead to ensure you are only reading signed data.
+ *
+ * The method does not return, but has some noteable exit-codes:
+ * 111 signals an internal error like the inability to execute gpgv,
+ * 112 indicates a clear-signed file which doesn't include a message,
+ *  which can happen if APT is run while on a network requiring
+ *  authentication before usage (e.g. in hotels)
+ * All other exit-codes are passed-through from gpgv.
  *
  *
  * @param File is the message (unsigned or clear-signed)
  * @param File is the message (unsigned or clear-signed)
  * @param FileSig is the signature (detached or clear-signed)
  * @param FileSig is the signature (detached or clear-signed)

+ 3 - 1
apt-pkg/contrib/sha2.h

@@ -60,10 +60,11 @@ class SHA256Summation : public SHA2SummationBase
       res.Set(Sum);
       res.Set(Sum);
       return res;
       return res;
    };
    };
-   SHA256Summation() 
+   SHA256Summation()
    {
    {
       SHA256_Init(&ctx);
       SHA256_Init(&ctx);
       Done = false;
       Done = false;
+      memset(&Sum, 0, sizeof(Sum));
    };
    };
 };
 };
 
 
@@ -96,6 +97,7 @@ class SHA512Summation : public SHA2SummationBase
    {
    {
       SHA512_Init(&ctx);
       SHA512_Init(&ctx);
       Done = false;
       Done = false;
+      memset(&Sum, 0, sizeof(Sum));
    };
    };
 };
 };
 
 

+ 6 - 6
apt-pkg/contrib/sha2_internal.cc

@@ -632,7 +632,7 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
 	}
 	}
 
 
 	/* Clean up state data: */
 	/* Clean up state data: */
-	MEMSET_BZERO(context, sizeof(context));
+	MEMSET_BZERO(context, sizeof(*context));
 	usedspace = 0;
 	usedspace = 0;
 }
 }
 
 
@@ -653,7 +653,7 @@ char *SHA256_End(SHA256_CTX* context, char buffer[]) {
 		}
 		}
 		*buffer = (char)0;
 		*buffer = (char)0;
 	} else {
 	} else {
-		MEMSET_BZERO(context, sizeof(context));
+		MEMSET_BZERO(context, sizeof(*context));
 	}
 	}
 	MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH);
 	MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH);
 	return buffer;
 	return buffer;
@@ -969,7 +969,7 @@ void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
 	}
 	}
 
 
 	/* Zero out state data */
 	/* Zero out state data */
-	MEMSET_BZERO(context, sizeof(context));
+	MEMSET_BZERO(context, sizeof(*context));
 }
 }
 
 
 char *SHA512_End(SHA512_CTX* context, char buffer[]) {
 char *SHA512_End(SHA512_CTX* context, char buffer[]) {
@@ -989,7 +989,7 @@ char *SHA512_End(SHA512_CTX* context, char buffer[]) {
 		}
 		}
 		*buffer = (char)0;
 		*buffer = (char)0;
 	} else {
 	} else {
-		MEMSET_BZERO(context, sizeof(context));
+		MEMSET_BZERO(context, sizeof(*context));
 	}
 	}
 	MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH);
 	MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH);
 	return buffer;
 	return buffer;
@@ -1044,7 +1044,7 @@ void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
 	}
 	}
 
 
 	/* Zero out state data */
 	/* Zero out state data */
-	MEMSET_BZERO(context, sizeof(context));
+	MEMSET_BZERO(context, sizeof(*context));
 }
 }
 
 
 char *SHA384_End(SHA384_CTX* context, char buffer[]) {
 char *SHA384_End(SHA384_CTX* context, char buffer[]) {
@@ -1064,7 +1064,7 @@ char *SHA384_End(SHA384_CTX* context, char buffer[]) {
 		}
 		}
 		*buffer = (char)0;
 		*buffer = (char)0;
 	} else {
 	} else {
-		MEMSET_BZERO(context, sizeof(context));
+		MEMSET_BZERO(context, sizeof(*context));
 	}
 	}
 	MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH);
 	MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH);
 	return buffer;
 	return buffer;

+ 10 - 9
apt-pkg/contrib/strutl.cc

@@ -759,7 +759,7 @@ bool ReadMessages(int Fd, vector<string> &List)
       for (char *I = Buffer; I + 1 < End; I++)
       for (char *I = Buffer; I + 1 < End; I++)
       {
       {
 	 if (I[1] != '\n' ||
 	 if (I[1] != '\n' ||
-	     (strncmp(I, "\n\n", 2) != 0 && strncmp(I, "\r\n\r\n", 4) != 0))
+	       (I[0] != '\n' && strncmp(I, "\r\n\r\n", 4) != 0))
 	    continue;
 	    continue;
 	 
 	 
 	 // Pull the message out
 	 // Pull the message out
@@ -767,7 +767,7 @@ bool ReadMessages(int Fd, vector<string> &List)
 	 PartialMessage += Message;
 	 PartialMessage += Message;
 
 
 	 // Fix up the buffer
 	 // Fix up the buffer
-	 for (; I < End && (*I == '\r' || *I == '\n'); ++I);
+	 for (; I < End && (*I == '\n' || *I == '\r'); ++I);
 	 End -= I-Buffer;	 
 	 End -= I-Buffer;	 
 	 memmove(Buffer,I,End-Buffer);
 	 memmove(Buffer,I,End-Buffer);
 	 I = Buffer;
 	 I = Buffer;
@@ -1233,12 +1233,12 @@ char *safe_snprintf(char *Buffer,char *End,const char *Format,...)
    va_list args;
    va_list args;
    int Did;
    int Did;
 
 
-   va_start(args,Format);
-
    if (End <= Buffer)
    if (End <= Buffer)
       return End;
       return End;
-
+   va_start(args,Format);
    Did = vsnprintf(Buffer,End - Buffer,Format,args);
    Did = vsnprintf(Buffer,End - Buffer,Format,args);
+   va_end(args);
+
    if (Did < 0 || Buffer + Did > End)
    if (Did < 0 || Buffer + Did > End)
       return End;
       return End;
    return Buffer + Did;
    return Buffer + Did;
@@ -1484,9 +1484,12 @@ URI::operator string()
           
           
       if (User.empty() == false)
       if (User.empty() == false)
       {
       {
-	 Res +=  User;
+	 // FIXME: Technically userinfo is permitted even less
+	 // characters than these, but this is not conveniently
+	 // expressed with a blacklist.
+	 Res += QuoteString(User, ":/?#[]@");
 	 if (Password.empty() == false)
 	 if (Password.empty() == false)
-	    Res += ":" + Password;
+	    Res += ":" + QuoteString(Password, ":/?#[]@");
 	 Res += "@";
 	 Res += "@";
       }
       }
       
       
@@ -1525,7 +1528,6 @@ string URI::SiteOnly(const string &URI)
    U.User.clear();
    U.User.clear();
    U.Password.clear();
    U.Password.clear();
    U.Path.clear();
    U.Path.clear();
-   U.Port = 0;
    return U;
    return U;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1537,7 +1539,6 @@ string URI::NoUserPassword(const string &URI)
    ::URI U(URI);
    ::URI U(URI);
    U.User.clear();
    U.User.clear();
    U.Password.clear();
    U.Password.clear();
-   U.Port = 0;
    return U;
    return U;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 24 - 86
apt-pkg/deb/deblistparser.cc

@@ -219,8 +219,12 @@ MD5SumValue debListParser::Description_md5()
    string const value = Section.FindS("Description-md5");
    string const value = Section.FindS("Description-md5");
    if (value.empty() == true)
    if (value.empty() == true)
    {
    {
+      std::string const desc = Description() + "\n";
+      if (desc == "\n")
+	 return MD5SumValue();
+
       MD5Summation md5;
       MD5Summation md5;
-      md5.Add((Description() + "\n").c_str());
+      md5.Add(desc.c_str());
       return md5.Result();
       return md5.Result();
    }
    }
    else if (likely(value.size() == 32))
    else if (likely(value.size() == 32))
@@ -801,94 +805,28 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
    map_ptrloc const storage = WriteUniqString(component);
    map_ptrloc const storage = WriteUniqString(component);
    FileI->Component = storage;
    FileI->Component = storage;
 
 
-   // FIXME: should use FileFd and TagSection
-   FILE* release = fdopen(dup(File.Fd()), "r");
-   if (release == NULL)
+   pkgTagFile TagFile(&File);
+   pkgTagSection Section;
+   if (_error->PendingError() == true || TagFile.Step(Section) == false)
       return false;
       return false;
 
 
-   char buffer[101];
-   while (fgets(buffer, sizeof(buffer), release) != NULL)
-   {
-      size_t len = 0;
-
-      // Skip empty lines
-      for (; buffer[len] == '\r' && buffer[len] == '\n'; ++len)
-         /* nothing */
-         ;
-      if (buffer[len] == '\0')
-	 continue;
-
-      // seperate the tag from the data
-      const char* dataStart = strchr(buffer + len, ':');
-      if (dataStart == NULL)
-	 continue;
-      len = dataStart - buffer;
-      for (++dataStart; *dataStart == ' '; ++dataStart)
-         /* nothing */
-         ;
-      const char* dataEnd = (const char*)rawmemchr(dataStart, '\0');
-      // The last char should be a newline, but we can never be sure: #633350
-      const char* lineEnd = dataEnd;
-      for (--lineEnd; *lineEnd == '\r' || *lineEnd == '\n'; --lineEnd)
-         /* nothing */
-         ;
-      ++lineEnd;
-
-      // which datastorage need to be updated
-      enum { Suite, Component, Version, Origin, Codename, Label, None } writeTo = None;
-      if (buffer[0] == ' ')
-	 ;
-      #define APT_PARSER_WRITETO(X) else if (strncmp(#X, buffer, len) == 0) writeTo = X;
-      APT_PARSER_WRITETO(Suite)
-      APT_PARSER_WRITETO(Component)
-      APT_PARSER_WRITETO(Version)
-      APT_PARSER_WRITETO(Origin)
-      APT_PARSER_WRITETO(Codename)
-      APT_PARSER_WRITETO(Label)
-      #undef APT_PARSER_WRITETO
-      #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
-	 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, lineEnd);
-      APT_PARSER_FLAGIT(NotAutomatic)
-      APT_PARSER_FLAGIT(ButAutomaticUpgrades)
-      #undef APT_PARSER_FLAGIT
-
-      // load all data from the line and save it
-      string data;
-      if (writeTo != None)
-	 data.append(dataStart, dataEnd);
-      if (sizeof(buffer) - 1 == (dataEnd - buffer))
-      {
-	 while (fgets(buffer, sizeof(buffer), release) != NULL)
-	 {
-	    if (writeTo != None)
-	       data.append(buffer);
-	    if (strlen(buffer) != sizeof(buffer) - 1)
-	       break;
-	 }
-      }
-      if (writeTo != None)
-      {
-	 // remove spaces and stuff from the end of the data line
-	 for (std::string::reverse_iterator s = data.rbegin();
-	      s != data.rend(); ++s)
-	 {
-	    if (*s != '\r' && *s != '\n' && *s != ' ')
-	       break;
-	    *s = '\0';
-	 }
-	 map_ptrloc const storage = WriteUniqString(data);
-	 switch (writeTo) {
-	 case Suite: FileI->Archive = storage; break;
-	 case Component: FileI->Component = storage; break;
-	 case Version: FileI->Version = storage; break;
-	 case Origin: FileI->Origin = storage; break;
-	 case Codename: FileI->Codename = storage; break;
-	 case Label: FileI->Label = storage; break;
-	 case None: break;
-	 }
-      }
+   std::string data;
+   #define APT_INRELEASE(TAG, STORE) \
+   data = Section.FindS(TAG); \
+   if (data.empty() == false) \
+   { \
+      map_ptrloc const storage = WriteUniqString(data); \
+      STORE = storage; \
    }
    }
-   fclose(release);
+   APT_INRELEASE("Suite", FileI->Archive)
+   APT_INRELEASE("Component", FileI->Component)
+   APT_INRELEASE("Version", FileI->Version)
+   APT_INRELEASE("Origin", FileI->Origin)
+   APT_INRELEASE("Codename", FileI->Codename)
+   APT_INRELEASE("Label", FileI->Label)
+   #undef APT_INRELEASE
+   Section.FindFlag("NotAutomatic", FileI->Flags, pkgCache::Flag::NotAutomatic);
+   Section.FindFlag("ButAutomaticUpgrades", FileI->Flags, pkgCache::Flag::ButAutomaticUpgrades);
 
 
    return !_error->PendingError();
    return !_error->PendingError();
 }
 }

+ 22 - 2
apt-pkg/deb/debmetaindex.cc

@@ -238,6 +238,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
 	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
 	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
 			 (*Target)->ShortDesc, HashString());
 			 (*Target)->ShortDesc, HashString());
       }
       }
+      delete targets;
 
 
       // this is normally created in pkgAcqMetaSig, but if we run
       // this is normally created in pkgAcqMetaSig, but if we run
       // in --print-uris mode, we add it here
       // in --print-uris mode, we add it here
@@ -373,10 +374,29 @@ class debSLTypeDebian : public pkgSourceList::Type
 			   string const &Dist, string const &Section,
 			   string const &Dist, string const &Section,
 			   bool const &IsSrc, map<string, string> const &Options) const
 			   bool const &IsSrc, map<string, string> const &Options) const
    {
    {
-      map<string, string>::const_iterator const arch = Options.find("arch");
-      vector<string> const Archs =
+      // parse arch=, arch+= and arch-= settings
+      map<string, string>::const_iterator arch = Options.find("arch");
+      vector<string> Archs =
 		(arch != Options.end()) ? VectorizeString(arch->second, ',') :
 		(arch != Options.end()) ? VectorizeString(arch->second, ',') :
 				APT::Configuration::getArchitectures();
 				APT::Configuration::getArchitectures();
+      if ((arch = Options.find("arch+")) != Options.end())
+      {
+	 std::vector<std::string> const plusArch = VectorizeString(arch->second, ',');
+	 for (std::vector<std::string>::const_iterator plus = plusArch.begin(); plus != plusArch.end(); ++plus)
+	    if (std::find(Archs.begin(), Archs.end(), *plus) == Archs.end())
+	       Archs.push_back(*plus);
+      }
+      if ((arch = Options.find("arch-")) != Options.end())
+      {
+	 std::vector<std::string> const minusArch = VectorizeString(arch->second, ',');
+	 for (std::vector<std::string>::const_iterator minus = minusArch.begin(); minus != minusArch.end(); ++minus)
+	 {
+	    std::vector<std::string>::iterator kill = std::find(Archs.begin(), Archs.end(), *minus);
+	    if (kill != Archs.end())
+	       Archs.erase(kill);
+	 }
+      }
+
       map<string, string>::const_iterator const trusted = Options.find("trusted");
       map<string, string>::const_iterator const trusted = Options.find("trusted");
 
 
       for (vector<metaIndex *>::const_iterator I = List.begin();
       for (vector<metaIndex *>::const_iterator I = List.begin();

+ 73 - 34
apt-pkg/deb/dpkgpm.cc

@@ -134,6 +134,8 @@ static void dpkgChrootDirectory()
    std::cerr << "Chrooting into " << chrootDir << std::endl;
    std::cerr << "Chrooting into " << chrootDir << std::endl;
    if (chroot(chrootDir.c_str()) != 0)
    if (chroot(chrootDir.c_str()) != 0)
       _exit(100);
       _exit(100);
+   if (chdir("/") != 0)
+      _exit(100);
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 
@@ -238,15 +240,23 @@ bool pkgDPkgPM::Remove(PkgIterator Pkg,bool Purge)
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// DPkgPM::SendV2Pkgs - Send version 2 package info			/*{{{*/
+// DPkgPM::SendPkgInfo - Send info for install-pkgs hook		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is part of the helper script communication interface, it sends
 /* This is part of the helper script communication interface, it sends
    very complete information down to the other end of the pipe.*/
    very complete information down to the other end of the pipe.*/
 bool pkgDPkgPM::SendV2Pkgs(FILE *F)
 bool pkgDPkgPM::SendV2Pkgs(FILE *F)
 {
 {
-   fprintf(F,"VERSION 2\n");
-   
-   /* Write out all of the configuration directives by walking the 
+   return SendPkgsInfo(F, 2);
+}
+bool pkgDPkgPM::SendPkgsInfo(FILE * const F, unsigned int const &Version)
+{
+   // This version of APT supports only v3, so don't sent higher versions
+   if (Version <= 3)
+      fprintf(F,"VERSION %u\n", Version);
+   else
+      fprintf(F,"VERSION 3\n");
+
+   /* Write out all of the configuration directives by walking the
       configuration tree */
       configuration tree */
    const Configuration::Item *Top = _config->Tree(0);
    const Configuration::Item *Top = _config->Tree(0);
    for (; Top != 0;)
    for (; Top != 0;)
@@ -280,30 +290,51 @@ bool pkgDPkgPM::SendV2Pkgs(FILE *F)
       pkgDepCache::StateCache &S = Cache[I->Pkg];
       pkgDepCache::StateCache &S = Cache[I->Pkg];
       
       
       fprintf(F,"%s ",I->Pkg.Name());
       fprintf(F,"%s ",I->Pkg.Name());
-      // Current version
-      if (I->Pkg->CurrentVer == 0)
-	 fprintf(F,"- ");
+
+      // Current version which we are going to replace
+      pkgCache::VerIterator CurVer = I->Pkg.CurrentVer();
+      if (CurVer.end() == true && (I->Op == Item::Remove || I->Op == Item::Purge))
+	 CurVer = FindNowVersion(I->Pkg);
+
+      if (CurVer.end() == true)
+      {
+	 if (Version <= 2)
+	    fprintf(F, "- ");
+	 else
+	    fprintf(F, "- - none ");
+      }
       else
       else
-	 fprintf(F,"%s ",I->Pkg.CurrentVer().VerStr());
-      
-      // Show the compare operator
-      // Target version
+      {
+	 fprintf(F, "%s ", CurVer.VerStr());
+	 if (Version >= 3)
+	    fprintf(F, "%s %s ", CurVer.Arch(), CurVer.MultiArchType());
+      }
+
+      // Show the compare operator between current and install version
       if (S.InstallVer != 0)
       if (S.InstallVer != 0)
       {
       {
+	 pkgCache::VerIterator const InstVer = S.InstVerIter(Cache);
 	 int Comp = 2;
 	 int Comp = 2;
-	 if (I->Pkg->CurrentVer != 0)
-	    Comp = S.InstVerIter(Cache).CompareVer(I->Pkg.CurrentVer());
+	 if (CurVer.end() == false)
+	    Comp = InstVer.CompareVer(CurVer);
 	 if (Comp < 0)
 	 if (Comp < 0)
 	    fprintf(F,"> ");
 	    fprintf(F,"> ");
-	 if (Comp == 0)
+	 else if (Comp == 0)
 	    fprintf(F,"= ");
 	    fprintf(F,"= ");
-	 if (Comp > 0)
+	 else if (Comp > 0)
 	    fprintf(F,"< ");
 	    fprintf(F,"< ");
-	 fprintf(F,"%s ",S.InstVerIter(Cache).VerStr());
+	 fprintf(F, "%s ", InstVer.VerStr());
+	 if (Version >= 3)
+	    fprintf(F, "%s %s ", InstVer.Arch(), InstVer.MultiArchType());
       }
       }
       else
       else
-	 fprintf(F,"> - ");
-      
+      {
+	 if (Version <= 2)
+	    fprintf(F, "> - ");
+	 else
+	    fprintf(F, "> - - none ");
+      }
+
       // Show the filename/operation
       // Show the filename/operation
       if (I->Op == Item::Install)
       if (I->Op == Item::Install)
       {
       {
@@ -313,9 +344,9 @@ bool pkgDPkgPM::SendV2Pkgs(FILE *F)
 	 else
 	 else
 	    fprintf(F,"%s\n",I->File.c_str());
 	    fprintf(F,"%s\n",I->File.c_str());
       }      
       }      
-      if (I->Op == Item::Configure)
+      else if (I->Op == Item::Configure)
 	 fprintf(F,"**CONFIGURE**\n");
 	 fprintf(F,"**CONFIGURE**\n");
-      if (I->Op == Item::Remove ||
+      else if (I->Op == Item::Remove ||
 	  I->Op == Item::Purge)
 	  I->Op == Item::Purge)
 	 fprintf(F,"**REMOVE**\n");
 	 fprintf(F,"**REMOVE**\n");
       
       
@@ -404,7 +435,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
 	 }
 	 }
       }
       }
       else
       else
-	 SendV2Pkgs(F);
+	 SendPkgsInfo(F, Version);
 
 
       fclose(F);
       fclose(F);
       
       
@@ -720,13 +751,15 @@ bool pkgDPkgPM::OpenLog()
 	 return _error->WarningE("OpenLog", _("Could not open file '%s'"), logfile_name.c_str());
 	 return _error->WarningE("OpenLog", _("Could not open file '%s'"), logfile_name.c_str());
       setvbuf(d->term_out, NULL, _IONBF, 0);
       setvbuf(d->term_out, NULL, _IONBF, 0);
       SetCloseExec(fileno(d->term_out), true);
       SetCloseExec(fileno(d->term_out), true);
-      struct passwd *pw;
-      struct group *gr;
-      pw = getpwnam("root");
-      gr = getgrnam("adm");
-      if (pw != NULL && gr != NULL)
-	  chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid);
-      chmod(logfile_name.c_str(), 0640);
+      if (getuid() == 0) // if we aren't root, we can't chown a file, so don't try it
+      {
+	 struct passwd *pw = getpwnam("root");
+	 struct group *gr = getgrnam("adm");
+	 if (pw != NULL && gr != NULL && chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid) != 0)
+	    _error->WarningE("OpenLog", "chown to root:adm of file %s failed", logfile_name.c_str());
+      }
+      if (chmod(logfile_name.c_str(), 0640) != 0)
+	 _error->WarningE("OpenLog", "chmod 0640 of file %s failed", logfile_name.c_str());
       fprintf(d->term_out, "\nLog started: %s\n", timestr);
       fprintf(d->term_out, "\nLog started: %s\n", timestr);
    }
    }
 
 
@@ -1205,16 +1238,13 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 
 
       // if tcgetattr does not return zero there was a error
       // if tcgetattr does not return zero there was a error
       // and we do not do any pty magic
       // and we do not do any pty magic
+      _error->PushToStack();
       if (tcgetattr(STDOUT_FILENO, &tt) == 0)
       if (tcgetattr(STDOUT_FILENO, &tt) == 0)
       {
       {
 	 ioctl(0, TIOCGWINSZ, (char *)&win);
 	 ioctl(0, TIOCGWINSZ, (char *)&win);
-	 if (openpty(&master, &slave, NULL, &tt, &win) < 0) 
+	 if (openpty(&master, &slave, NULL, &tt, &win) < 0)
 	 {
 	 {
-	    const char *s = _("Can not write log, openpty() "
-	                      "failed (/dev/pts not mounted?)\n");
-	    fprintf(stderr, "%s",s);
-            if(d->term_out)
-              fprintf(d->term_out, "%s",s);
+	    _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
 	    master = slave = -1;
 	    master = slave = -1;
 	 }  else {
 	 }  else {
 	    struct termios rtt;
 	    struct termios rtt;
@@ -1237,6 +1267,15 @@ bool pkgDPkgPM::Go(int OutStatusFd)
          if(d->term_out)
          if(d->term_out)
             fprintf(d->term_out, "%s",s); 
             fprintf(d->term_out, "%s",s); 
       }
       }
+      // complain only if stdout is either a terminal (but still failed) or is an invalid
+      // descriptor otherwise we would complain about redirection to e.g. /dev/null as well.
+      else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF)
+         _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?"));
+
+      if (_error->PendingError() == true)
+	 _error->DumpErrors(std::cerr);
+      _error->RevertToStack();
+
        // Fork dpkg
        // Fork dpkg
       pid_t Child;
       pid_t Child;
       _config->Set("APT::Keep-Fds::",fd[1]);
       _config->Set("APT::Keep-Fds::",fd[1]);

+ 3 - 1
apt-pkg/deb/dpkgpm.h

@@ -14,6 +14,7 @@
 #include <vector>
 #include <vector>
 #include <map>
 #include <map>
 #include <stdio.h>
 #include <stdio.h>
+#include <apt-pkg/macros.h>
 
 
 #ifndef APT_8_CLEANER_HEADERS
 #ifndef APT_8_CLEANER_HEADERS
 using std::vector;
 using std::vector;
@@ -79,7 +80,8 @@ class pkgDPkgPM : public pkgPackageManager
 
 
    // Helpers
    // Helpers
    bool RunScriptsWithPkgs(const char *Cnf);
    bool RunScriptsWithPkgs(const char *Cnf);
-   bool SendV2Pkgs(FILE *F);
+   __deprecated bool SendV2Pkgs(FILE *F);
+   bool SendPkgsInfo(FILE * const F, unsigned int const &Version);
    void WriteHistoryTag(std::string const &tag, std::string value);
    void WriteHistoryTag(std::string const &tag, std::string value);
 
 
    // apport integration
    // apport integration

+ 75 - 15
apt-pkg/depcache.cc

@@ -864,6 +864,11 @@ bool pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
    dpkg holds are enforced by the private IsModeChangeOk */
    dpkg holds are enforced by the private IsModeChangeOk */
 bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge,
 bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge,
 			      unsigned long Depth, bool FromUser)
 			      unsigned long Depth, bool FromUser)
+{
+   return IsDeleteOkProtectInstallRequests(Pkg, rPurge, Depth, FromUser);
+}
+bool pkgDepCache::IsDeleteOkProtectInstallRequests(PkgIterator const &Pkg,
+      bool const rPurge, unsigned long const Depth, bool const FromUser)
 {
 {
    if (FromUser == false && Pkg->CurrentVer == 0)
    if (FromUser == false && Pkg->CurrentVer == 0)
    {
    {
@@ -1002,9 +1007,6 @@ struct CompareProviders {
 	 else if ((B->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
 	 else if ((B->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
 	    return true;
 	    return true;
       }
       }
-      // higher priority seems like a good idea
-      if (AV->Priority != BV->Priority)
-	 return AV->Priority < BV->Priority;
       // prefer native architecture
       // prefer native architecture
       if (strcmp(A.Arch(), B.Arch()) != 0)
       if (strcmp(A.Arch(), B.Arch()) != 0)
       {
       {
@@ -1019,6 +1021,9 @@ struct CompareProviders {
 	    else if (*a == B.Arch())
 	    else if (*a == B.Arch())
 	       return true;
 	       return true;
       }
       }
+      // higher priority seems like a good idea
+      if (AV->Priority != BV->Priority)
+	 return AV->Priority > BV->Priority;
       // unable to decide…
       // unable to decide…
       return A->ID < B->ID;
       return A->ID < B->ID;
    }
    }
@@ -1047,9 +1052,10 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
       return true;
       return true;
    }
    }
 
 
-   // check if we are allowed to install the package
-   if (IsInstallOk(Pkg,AutoInst,Depth,FromUser) == false)
-      return false;
+   // check if we are allowed to install the package (if we haven't already)
+   if (P.Mode != ModeInstall || P.InstallVer != P.CandidateVer)
+      if (IsInstallOk(Pkg,AutoInst,Depth,FromUser) == false)
+	 return false;
 
 
    ActionGroup group(*this);
    ActionGroup group(*this);
    P.iFlags &= ~AutoKept;
    P.iFlags &= ~AutoKept;
@@ -1200,16 +1206,23 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	    verlist.insert(Cand);
 	    verlist.insert(Cand);
 	 }
 	 }
 	 CompareProviders comp(Start);
 	 CompareProviders comp(Start);
-	 APT::VersionList::iterator InstVer = std::max_element(verlist.begin(), verlist.end(), comp);
 
 
-	 if (InstVer != verlist.end())
-	 {
+	 do {
+	    APT::VersionList::iterator InstVer = std::max_element(verlist.begin(), verlist.end(), comp);
+
+	    if (InstVer == verlist.end())
+	       break;
+
 	    pkgCache::PkgIterator InstPkg = InstVer.ParentPkg();
 	    pkgCache::PkgIterator InstPkg = InstVer.ParentPkg();
 	    if(DebugAutoInstall == true)
 	    if(DebugAutoInstall == true)
 	       std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name()
 	       std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name()
 			 << " as " << Start.DepType() << " of " << Pkg.Name()
 			 << " as " << Start.DepType() << " of " << Pkg.Name()
 			 << std::endl;
 			 << std::endl;
-	    MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps);
+	    if (MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps) == false)
+	    {
+	       verlist.erase(InstVer);
+	       continue;
+	    }
 	    // now check if we should consider it a automatic dependency or not
 	    // now check if we should consider it a automatic dependency or not
 	    if(InstPkg->CurrentVer == 0 && Pkg->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
 	    if(InstPkg->CurrentVer == 0 && Pkg->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
 	    {
 	    {
@@ -1218,7 +1231,8 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
                             << Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl;
                             << Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl;
 	       MarkAuto(InstPkg, false);
 	       MarkAuto(InstPkg, false);
 	    }
 	    }
-	 }
+	    break;
+	 } while(true);
 	 continue;
 	 continue;
       }
       }
       /* Negative dependencies have no or-group
       /* Negative dependencies have no or-group
@@ -1243,9 +1257,16 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 		PkgState[Pkg->ID].CandidateVer != *I &&
 		PkgState[Pkg->ID].CandidateVer != *I &&
 		MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps) == true)
 		MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps) == true)
 	       continue;
 	       continue;
-	    else if ((Start->Type == pkgCache::Dep::Conflicts || Start->Type == pkgCache::Dep::DpkgBreaks) &&
-		     MarkDelete(Pkg,false,Depth + 1, false) == false)
-	       break;
+	    else if (Start->Type == pkgCache::Dep::Conflicts || 
+                     Start->Type == pkgCache::Dep::DpkgBreaks) 
+            {
+               if(DebugAutoInstall == true)
+                  std::clog << OutputInDepth(Depth) 
+                            << " Removing: " << Pkg.Name()
+                            << std::endl;
+               if (MarkDelete(Pkg,false,Depth + 1, false) == false)
+                  break;
+            }
 	 }
 	 }
 	 continue;
 	 continue;
       }
       }
@@ -1256,11 +1277,50 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 									/*}}}*/
 									/*}}}*/
 // DepCache::IsInstallOk - check if it is ok to install this package	/*{{{*/
 // DepCache::IsInstallOk - check if it is ok to install this package	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* The default implementation does nothing.
+/* The default implementation checks if the installation of an M-A:same
+   package would lead us into a version-screw and if so forbids it.
    dpkg holds are enforced by the private IsModeChangeOk */
    dpkg holds are enforced by the private IsModeChangeOk */
 bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
 bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
 			      unsigned long Depth, bool FromUser)
 			      unsigned long Depth, bool FromUser)
 {
 {
+   return IsInstallOkMultiArchSameVersionSynced(Pkg,AutoInst, Depth, FromUser);
+}
+bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg,
+      bool const AutoInst, unsigned long const Depth, bool const FromUser)
+{
+   if (FromUser == true) // as always: user is always right
+      return true;
+
+   // ignore packages with none-M-A:same candidates
+   VerIterator const CandVer = PkgState[Pkg->ID].CandidateVerIter(*this);
+   if (unlikely(CandVer.end() == true) || CandVer == Pkg.CurrentVer() ||
+	 (CandVer->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same)
+      return true;
+
+   GrpIterator const Grp = Pkg.Group();
+   for (PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P))
+   {
+      // not installed or version synced: fine by definition
+      // (simple string-compare as stuff like '1' == '0:1-0' can't happen here)
+      if (P->CurrentVer == 0 || strcmp(Pkg.CandVersion(), P.CandVersion()) == 0)
+	 continue;
+      // packages loosing M-A:same can be out-of-sync
+      VerIterator CV = PkgState[P->ID].CandidateVerIter(*this);
+      if (unlikely(CV.end() == true) ||
+	    (CV->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same)
+	 continue;
+
+      // not downloadable means the package is obsolete, so allow out-of-sync
+      if (CV.Downloadable() == false)
+	 continue;
+
+      PkgState[Pkg->ID].iFlags |= AutoKept;
+      if (unlikely(DebugMarker == true))
+	 std::clog << OutputInDepth(Depth) << "Ignore MarkInstall of " << Pkg
+	    << " as its M-A:same siblings are not version-synced" << std::endl;
+      return false;
+   }
+
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 17 - 13
apt-pkg/depcache.h

@@ -442,16 +442,15 @@ class pkgDepCache : protected pkgCache::Namespace
    /** \return \b true if it's OK for MarkInstall to install
    /** \return \b true if it's OK for MarkInstall to install
     *  the given package.
     *  the given package.
     *
     *
-    *  See the default implementation for a simple example how this
-    *  method can be used.
-    *  Overriding implementations should use the hold-state-flag to cache
-    *  results from previous checks of this package - also it should
-    *  be used if the default resolver implementation is also used to
-    *  ensure that these packages are handled like "normal" dpkg holds.
+    *  The default implementation simply calls all IsInstallOk*
+    *  method mentioned below.
+    *
+    *  Overriding implementations should use the hold-state-flag to
+    *  cache results from previous checks of this package - if possible.
     *
     *
     *  The parameters are the same as in the calling MarkInstall:
     *  The parameters are the same as in the calling MarkInstall:
     *  \param Pkg       the package that MarkInstall wants to install.
     *  \param Pkg       the package that MarkInstall wants to install.
-    *  \param AutoInst  needs a previous MarkInstall this package?
+    *  \param AutoInst  install this and all its dependencies
     *  \param Depth     recursive deep of this Marker call
     *  \param Depth     recursive deep of this Marker call
     *  \param FromUser  was the install requested by the user?
     *  \param FromUser  was the install requested by the user?
     */
     */
@@ -461,12 +460,8 @@ class pkgDepCache : protected pkgCache::Namespace
    /** \return \b true if it's OK for MarkDelete to remove
    /** \return \b true if it's OK for MarkDelete to remove
     *  the given package.
     *  the given package.
     *
     *
-    *  See the default implementation for a simple example how this
-    *  method can be used.
-    *  Overriding implementations should use the hold-state-flag to cache
-    *  results from previous checks of this package - also it should
-    *  be used if the default resolver implementation is also used to
-    *  ensure that these packages are handled like "normal" dpkg holds.
+    *  The default implementation simply calls all IsDeleteOk*
+    *  method mentioned below, see also #IsInstallOk.
     *
     *
     *  The parameters are the same as in the calling MarkDelete:
     *  The parameters are the same as in the calling MarkDelete:
     *  \param Pkg       the package that MarkDelete wants to remove.
     *  \param Pkg       the package that MarkDelete wants to remove.
@@ -498,6 +493,15 @@ class pkgDepCache : protected pkgCache::Namespace
    pkgDepCache(pkgCache *Cache,Policy *Plcy = 0);
    pkgDepCache(pkgCache *Cache,Policy *Plcy = 0);
    virtual ~pkgDepCache();
    virtual ~pkgDepCache();
 
 
+   protected:
+   // methods call by IsInstallOk
+   bool IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg,
+	 bool const AutoInst, unsigned long const Depth, bool const FromUser);
+
+   // methods call by IsDeleteOk
+   bool IsDeleteOkProtectInstallRequests(PkgIterator const &Pkg,
+	 bool const rPurge, unsigned long const Depth, bool const FromUser);
+
    private:
    private:
    bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
    bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg,
 			unsigned long const Depth, bool const FromUser);
 			unsigned long const Depth, bool const FromUser);

+ 17 - 6
apt-pkg/indexcopy.cc

@@ -106,9 +106,9 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
       } else {
       } else {
          Target.Open(TargetF,FileFd::WriteAtomic);
          Target.Open(TargetF,FileFd::WriteAtomic);
       }
       }
-      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
       if (_error->PendingError() == true)
       if (_error->PendingError() == true)
 	 return false;
 	 return false;
+      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
       if (TargetFl == 0)
       if (TargetFl == 0)
 	 return _error->Errno("fdopen","Failed to reopen fd");
 	 return _error->Errno("fdopen","Failed to reopen fd");
       
       
@@ -544,11 +544,9 @@ bool SigVerify::CopyMetaIndex(string CDROM, string CDName,		/*{{{*/
       FileFd Rel;
       FileFd Rel;
       Target.Open(TargetF,FileFd::WriteAtomic);
       Target.Open(TargetF,FileFd::WriteAtomic);
       Rel.Open(prefix + file,FileFd::ReadOnly);
       Rel.Open(prefix + file,FileFd::ReadOnly);
-      if (_error->PendingError() == true)
-	 return false;
       if (CopyFile(Rel,Target) == false)
       if (CopyFile(Rel,Target) == false)
-	 return false;
-   
+	 return _error->Error("Copying of '%s' for '%s' from '%s' failed", file.c_str(), CDName.c_str(), prefix.c_str());
+
       return true;
       return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -603,6 +601,7 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
 			 (useInRelease ? inrelease.c_str() : releasegpg.c_str()));
 			 (useInRelease ? inrelease.c_str() : releasegpg.c_str()));
 	 // something went wrong, don't copy the Release.gpg
 	 // something went wrong, don't copy the Release.gpg
 	 // FIXME: delete any existing gpg file?
 	 // FIXME: delete any existing gpg file?
+	 delete MetaIndex;
 	 continue;
 	 continue;
       }
       }
 
 
@@ -642,6 +641,18 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
+// SigVerify::RunGPGV - deprecated wrapper calling ExecGPGV		/*{{{*/
+bool SigVerify::RunGPGV(std::string const &File, std::string const &FileOut,
+      int const &statusfd, int fd[2]) {
+   ExecGPGV(File, FileOut, statusfd, fd);
+   return false;
+};
+bool SigVerify::RunGPGV(std::string const &File, std::string const &FileOut,
+      int const &statusfd) {
+   ExecGPGV(File, FileOut, statusfd);
+   return false;
+};
+									/*}}}*/
 bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
 bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
 				vector<string> &List, pkgCdromStatus *log)
 				vector<string> &List, pkgCdromStatus *log)
 {
 {
@@ -704,9 +715,9 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
       } else {
       } else {
 	 Target.Open(TargetF,FileFd::WriteAtomic);
 	 Target.Open(TargetF,FileFd::WriteAtomic);
       }
       }
-      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
       if (_error->PendingError() == true)
       if (_error->PendingError() == true)
 	 return false;
 	 return false;
+      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
       if (TargetFl == 0)
       if (TargetFl == 0)
 	 return _error->Errno("fdopen","Failed to reopen fd");
 	 return _error->Errno("fdopen","Failed to reopen fd");
       
       

+ 2 - 8
apt-pkg/indexcopy.h

@@ -100,15 +100,9 @@ class SigVerify								/*{{{*/
 		      std::vector<std::string> PkgList,std::vector<std::string> SrcList);
 		      std::vector<std::string> PkgList,std::vector<std::string> SrcList);
 
 
    __deprecated static bool RunGPGV(std::string const &File, std::string const &FileOut,
    __deprecated static bool RunGPGV(std::string const &File, std::string const &FileOut,
-		       int const &statusfd, int fd[2]) {
-      ExecGPGV(File, FileOut, statusfd, fd);
-      return false;
-   };
+		       int const &statusfd, int fd[2]);
    __deprecated static bool RunGPGV(std::string const &File, std::string const &FileOut,
    __deprecated static bool RunGPGV(std::string const &File, std::string const &FileOut,
-			      int const &statusfd = -1) {
-      ExecGPGV(File, FileOut, statusfd);
-      return false;
-   };
+			      int const &statusfd = -1);
 };
 };
 									/*}}}*/
 									/*}}}*/
 
 

+ 6 - 11
apt-pkg/indexrecords.cc

@@ -62,7 +62,7 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
    if (OpenMaybeClearSignedFile(Filename, Fd) == false)
    if (OpenMaybeClearSignedFile(Filename, Fd) == false)
       return false;
       return false;
 
 
-   pkgTagFile TagFile(&Fd, Fd.Size() + 256); // XXX
+   pkgTagFile TagFile(&Fd);
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
    {
    {
       strprintf(ErrorText, _("Unable to parse Release file %s"),Filename.c_str());
       strprintf(ErrorText, _("Unable to parse Release file %s"),Filename.c_str());
@@ -71,16 +71,11 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
 
 
    pkgTagSection Section;
    pkgTagSection Section;
    const char *Start, *End;
    const char *Start, *End;
-   // Skip over sections beginning with ----- as this is an idicator for clearsigns
-   do {
-      if (TagFile.Step(Section) == false)
-      {
-	 strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str());
-	 return false;
-      }
-
-      Section.Get (Start, End, 0);
-   } while (End - Start > 5 && strncmp(Start, "-----", 5) == 0);
+   if (TagFile.Step(Section) == false)
+   {
+      strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str());
+      return false;
+   }
 
 
    Suite = Section.FindS("Suite");
    Suite = Section.FindS("Suite");
    Dist = Section.FindS("Codename");
    Dist = Section.FindS("Codename");

+ 105 - 119
apt-pkg/orderlist.cc

@@ -301,9 +301,8 @@ bool pkgOrderList::OrderConfigure()
 /* Higher scores order earlier */
 /* Higher scores order earlier */
 int pkgOrderList::Score(PkgIterator Pkg)
 int pkgOrderList::Score(PkgIterator Pkg)
 {
 {
-   static int const ScoreDelete = _config->FindI("OrderList::Score::Delete", 500);
-
-   // Removal is always done first
+   // Removals should be done after we dealt with essentials
+   static int const ScoreDelete = _config->FindI("OrderList::Score::Delete", 100);
    if (Cache[Pkg].Delete() == true)
    if (Cache[Pkg].Delete() == true)
       return ScoreDelete;
       return ScoreDelete;
 
 
@@ -893,149 +892,136 @@ bool pkgOrderList::DepConfigure(DepIterator D)
 									/*}}}*/
 									/*}}}*/
 // OrderList::DepRemove - Removal ordering				/*{{{*/
 // OrderList::DepRemove - Removal ordering				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* Removal visits all reverse depends. It considers if the dependency
-   of the Now state version to see if it is okay with removing this
-   package. This check should always fail, but is provided for symetery
-   with the other critical handlers.
- 
-   Loops are preprocessed and logged. Removal loops can also be
-   detected in the critical handler. They are characterized by an
-   old version of A depending on B but the new version of A conflicting
-   with B, thus either A or B must break to install. */
-bool pkgOrderList::DepRemove(DepIterator D)
+/* Checks all given dependencies if they are broken by the remove of a
+   package and if so fix it by visiting another provider or or-group
+   member to ensure that the dependee keeps working which is especially
+   important for Immediate packages like e.g. those depending on an
+   awk implementation. If the dependency can't be fixed with another
+   package this means an upgrade of the package will solve the problem. */
+bool pkgOrderList::DepRemove(DepIterator Broken)
 {
 {
-   if (D.Reverse() == false)
+   if (Broken.Reverse() == false)
       return true;
       return true;
-   for (; D.end() == false; ++D)
-      if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
+
+   for (; Broken.end() == false; ++Broken)
+   {
+      if (Broken->Type != pkgCache::Dep::Depends &&
+	    Broken->Type != pkgCache::Dep::PreDepends)
+	 continue;
+
+      PkgIterator BrokenPkg = Broken.ParentPkg();
+      // uninstalled packages can't break via a remove
+      if (BrokenPkg->CurrentVer == 0)
+	 continue;
+
+      // if its already added, we can't do anything useful
+      if (IsFlag(BrokenPkg, AddPending) == true || IsFlag(BrokenPkg, Added) == true)
+	 continue;
+
+      // if the dependee is going to be removed, visit it now
+      if (Cache[BrokenPkg].Delete() == true)
+	 return VisitNode(BrokenPkg, "Remove-Dependee");
+
+      // The package stays around, so find out how this is possible
+      for (DepIterator D = BrokenPkg.CurrentVer().DependsList(); D.end() == false;)
       {
       {
-	 // Duplication elimination, consider the current version only
-	 if (D.ParentPkg().CurrentVer() != D.ParentVer())
+	 // only important or-groups need fixing
+	 if (D->Type != pkgCache::Dep::Depends &&
+	       D->Type != pkgCache::Dep::PreDepends)
+	 {
+	    ++D;
 	    continue;
 	    continue;
+	 }
 
 
-	 /* We wish to see if the dep on the parent package is okay
-	    in the removed (install) state of the target pkg. */
-	 bool tryFixDeps = false;
-	 if (CheckDep(D) == true)
+	 // Start is the beginning of the or-group, D is the first one after or
+	 DepIterator Start = D;
+	 bool foundBroken = false;
+	 for (bool LastOR = true; D.end() == false && LastOR == true; ++D)
 	 {
 	 {
-	    // We want to catch loops with the code below.
-	    if (IsFlag(D.ParentPkg(),AddPending) == false)
-	       continue;
+	    LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
+	    if (D == Broken)
+	       foundBroken = true;
 	 }
 	 }
-	 else
-	    tryFixDeps = true;
 
 
-	 // This is the loop detection
-	 if (IsFlag(D.ParentPkg(),Added) == true || 
-	     IsFlag(D.ParentPkg(),AddPending) == true)
-	 {
-	    if (IsFlag(D.ParentPkg(),AddPending) == true)
-	       AddLoop(D);
+	 // this or-group isn't the broken one: keep searching
+	 if (foundBroken == false)
 	    continue;
 	    continue;
+
+	 // iterate over all members of the or-group searching for a ready replacement
+	 bool readyReplacement = false;
+	 for (DepIterator OrMember = Start; OrMember != D && readyReplacement == false; ++OrMember)
+	 {
+	    Version ** Replacements = OrMember.AllTargets();
+	    for (Version **R = Replacements; *R != 0; ++R)
+	    {
+	       VerIterator Ver(Cache,*R);
+	       // only currently installed packages can be a replacement
+	       PkgIterator RPkg = Ver.ParentPkg();
+	       if (RPkg.CurrentVer() != Ver)
+		  continue;
+
+	       // packages going to be removed can't be a replacement
+	       if (Cache[RPkg].Delete() == true)
+		  continue;
+
+	       readyReplacement = true;
+	       break;
+	    }
+	    delete[] Replacements;
 	 }
 	 }
 
 
-	 if (tryFixDeps == true)
+	 // something else is ready to take over, do nothing
+	 if (readyReplacement == true)
+	    continue;
+
+	 // see if we can visit a replacement
+	 bool visitReplacement = false;
+	 for (DepIterator OrMember = Start; OrMember != D && visitReplacement == false; ++OrMember)
 	 {
 	 {
-	    for (pkgCache::DepIterator F = D.ParentPkg().CurrentVer().DependsList();
-		 F.end() == false; ++F)
+	    Version ** Replacements = OrMember.AllTargets();
+	    for (Version **R = Replacements; *R != 0; ++R)
 	    {
 	    {
-	       if (F->Type != pkgCache::Dep::Depends && F->Type != pkgCache::Dep::PreDepends)
+	       VerIterator Ver(Cache,*R);
+	       // consider only versions we plan to install
+	       PkgIterator RPkg = Ver.ParentPkg();
+	       if (Cache[RPkg].Install() == false || Cache[RPkg].InstallVer != Ver)
 		  continue;
 		  continue;
-	       // Check the Providers
-	       if (F.TargetPkg()->ProvidesList != 0)
-	       {
-		  pkgCache::PrvIterator Prov = F.TargetPkg().ProvidesList();
-		  for (; Prov.end() == false; ++Prov)
-		  {
-		     pkgCache::PkgIterator const P = Prov.OwnerPkg();
-		     if (IsFlag(P, InList) == true &&
-			 IsFlag(P, AddPending) == true &&
-			 IsFlag(P, Added) == false &&
-			 Cache[P].InstallVer == 0)
-			break;
-		  }
-		  if (Prov.end() == false)
-		     for (pkgCache::PrvIterator Prv = F.TargetPkg().ProvidesList();
-			  Prv.end() == false; ++Prv)
-		     {
-			pkgCache::PkgIterator const P = Prv.OwnerPkg();
-			if (IsFlag(P, InList) == true &&
-			    IsFlag(P, AddPending) == false &&
-			    Cache[P].InstallVer != 0 &&
-			    VisitNode(P, "Remove-P") == true)
-			{
-			   Flag(P, Immediate);
-			   tryFixDeps = false;
-			   break;
-			}
-		     }
-		  if (tryFixDeps == false)
-		     break;
-	       }
 
 
-	       // Check for Or groups
-	       if ((F->CompareOp & pkgCache::Dep::Or) != pkgCache::Dep::Or)
+	       // loops are not going to help us, so don't create them
+	       if (IsFlag(RPkg, AddPending) == true)
 		  continue;
 		  continue;
-	       // Lets see if the package is part of the Or group
-	       pkgCache::DepIterator S = F;
-	       for (; S.end() == false; ++S)
+
+	       if (IsMissing(RPkg) == true)
+		  continue;
+
+	       visitReplacement = true;
+	       if (IsFlag(BrokenPkg, Immediate) == false)
 	       {
 	       {
-		  if (S.TargetPkg() == D.TargetPkg())
+		  if (VisitNode(RPkg, "Remove-Rep") == true)
 		     break;
 		     break;
-		  if ((S->CompareOp & pkgCache::Dep::Or) != pkgCache::Dep::Or ||
-		      CheckDep(S)) // Or group is satisfied by another package
-		     for (;S.end() == false; ++S);
 	       }
 	       }
-	       if (S.end() == true)
-		  continue;
-	       // skip to the end of the or group
-	       for (;S.end() == false && (S->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; ++S);
-	       ++S;
-	       // The soon to be removed is part of the Or group
-	       // start again in the or group and find something which will serve as replacement
-	       for (; F.end() == false && F != S; ++F)
+	       else
 	       {
 	       {
-		  if (IsFlag(F.TargetPkg(), InList) == true &&
-		      IsFlag(F.TargetPkg(), AddPending) == false &&
-		      Cache[F.TargetPkg()].InstallVer != 0 &&
-		      VisitNode(F.TargetPkg(), "Remove-Target") == true)
-		  {
-		     Flag(F.TargetPkg(), Immediate);
-		     tryFixDeps = false;
+		  Flag(RPkg, Immediate);
+		  if (VisitNode(RPkg, "Remove-ImmRep") == true)
 		     break;
 		     break;
-		  }
-		  else if (F.TargetPkg()->ProvidesList != 0)
-		  {
-		     pkgCache::PrvIterator Prv = F.TargetPkg().ProvidesList();
-		     for (; Prv.end() == false; ++Prv)
-		     {
-			if (IsFlag(Prv.OwnerPkg(), InList) == true &&
-			    IsFlag(Prv.OwnerPkg(), AddPending) == false &&
-			    Cache[Prv.OwnerPkg()].InstallVer != 0 &&
-			    VisitNode(Prv.OwnerPkg(), "Remove-Owner") == true)
-			{
-			   Flag(Prv.OwnerPkg(), Immediate);
-			   tryFixDeps = false;
-			   break;
-			}
-		     }
-		     if (Prv.end() == false)
-			break;
-		  }
 	       }
 	       }
-	       if (tryFixDeps == false)
-		  break;
+	       visitReplacement = false;
 	    }
 	    }
+	    delete[] Replacements;
 	 }
 	 }
-
-	 // Skip over missing files
-	 if (IsMissing(D.ParentPkg()) == true)
+	 if (visitReplacement == true)
 	    continue;
 	    continue;
-	 
-	 if (VisitNode(D.ParentPkg(), "Remove-Parent") == false)
+
+	 // the broken package in current version can't be fixed, so install new version
+	 if (IsMissing(BrokenPkg) == true)
+	    break;
+
+	 if (VisitNode(BrokenPkg, "Remove-Upgrade") == false)
 	    return false;
 	    return false;
       }
       }
-   
+   }
+
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 73 - 48
apt-pkg/packagemanager.cc

@@ -338,8 +338,9 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
       however if there is a loop (A depends on B, B depends on A) this will not 
       however if there is a loop (A depends on B, B depends on A) this will not 
       be the case, so check for dependencies before configuring. */
       be the case, so check for dependencies before configuring. */
    bool Bad = false, Changed = false;
    bool Bad = false, Changed = false;
-   const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 500);
+   const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 5000);
    unsigned int i=0;
    unsigned int i=0;
+   std::list<DepIterator> needConfigure;
    do
    do
    {
    {
       Changed = false;
       Changed = false;
@@ -353,7 +354,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 	    continue;
 	    continue;
 	 Bad = true;
 	 Bad = true;
 
 
-	 // Search for dependencies which are unpacked but aren't configured yet (maybe loops)
+	 // Check for dependencies that have not been unpacked, probably due to loops.
 	 for (DepIterator Cur = Start; true; ++Cur)
 	 for (DepIterator Cur = Start; true; ++Cur)
 	 {
 	 {
 	    SPtrArray<Version *> VList = Cur.AllTargets();
 	    SPtrArray<Version *> VList = Cur.AllTargets();
@@ -373,51 +374,66 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 	       }
 	       }
 
 
 	       // Check if the version that is going to be installed will satisfy the dependency
 	       // Check if the version that is going to be installed will satisfy the dependency
-	       if (Cache[DepPkg].InstallVer != *I)
+	       if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false)
 		  continue;
 		  continue;
 
 
-	       if (List->IsFlag(DepPkg,pkgOrderList::UnPacked))
+	       if (PkgLoop == true)
 	       {
 	       {
-		  if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop)
-		  {
-		    // This dependency has already been dealt with by another SmartConfigure on Pkg
-		    Bad = false;
-		    break;
-		  }
-		  /* Check for a loop to prevent one forming
-		       If A depends on B and B depends on A, SmartConfigure will
-		       just hop between them if this is not checked. Dont remove the
-		       loop flag after finishing however as loop is already set.
-		       This means that there is another SmartConfigure call for this
-		       package and it will remove the loop flag */
+		  if (Debug)
+		     std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
+	          Bad = false;
+		  break;
+	       }
+	       else
+	       {
+		  if (Debug)
+		     clog << OutputInDepth(Depth) << "Unpacking " << DepPkg.FullName() << " to avoid loop " << Cur << endl;
 		  if (PkgLoop == false)
 		  if (PkgLoop == false)
 		     List->Flag(Pkg,pkgOrderList::Loop);
 		     List->Flag(Pkg,pkgOrderList::Loop);
-		  if (SmartConfigure(DepPkg, Depth + 1) == true)
+		  if (SmartUnPack(DepPkg, true, Depth + 1) == true)
 		  {
 		  {
 		     Bad = false;
 		     Bad = false;
 		     if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
 		     if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
-			Changed = true;
+		        Changed = true;
 		  }
 		  }
 		  if (PkgLoop == false)
 		  if (PkgLoop == false)
-		    List->RmFlag(Pkg,pkgOrderList::Loop);
-		  // If SmartConfigure was succesfull, Bad is false, so break
+		     List->RmFlag(Pkg,pkgOrderList::Loop);
 		  if (Bad == false)
 		  if (Bad == false)
 		     break;
 		     break;
 	       }
 	       }
-	       else if (List->IsFlag(DepPkg,pkgOrderList::Configured))
-	       {
-		  Bad = false;
-		  break;
-	       }
 	    }
 	    }
-	    if (Cur == End)
+
+	    if (Cur == End || Bad == false)
 	       break;
 	       break;
-         }
+	 }
 
 
 	 if (Bad == false)
 	 if (Bad == false)
 	    continue;
 	    continue;
 
 
-	 // Check for dependencies that have not been unpacked, probably due to loops.
+	 needConfigure.push_back(Start);
+      }
+      if (i++ > max_loops)
+         return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (1) for %s, aborting", Pkg.FullName().c_str());
+   } while (Changed == true);
+
+   Bad = false, Changed = false, i = 0;
+   do
+   {
+      Changed = false;
+      for (std::list<DepIterator>::const_iterator D = needConfigure.begin(); D != needConfigure.end(); ++D)
+      {
+	 // Compute a single dependency element (glob or) without modifying D
+	 pkgCache::DepIterator Start, End;
+	 {
+	    pkgCache::DepIterator Discard = *D;
+	    Discard.GlobOr(Start,End);
+	 }
+
+	 if (End->Type != pkgCache::Dep::Depends)
+	    continue;
+	 Bad = true;
+
+	 // Search for dependencies which are unpacked but aren't configured yet (maybe loops)
 	 for (DepIterator Cur = Start; true; ++Cur)
 	 for (DepIterator Cur = Start; true; ++Cur)
 	 {
 	 {
 	    SPtrArray<Version *> VList = Cur.AllTargets();
 	    SPtrArray<Version *> VList = Cur.AllTargets();
@@ -428,44 +444,53 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 	       PkgIterator DepPkg = Ver.ParentPkg();
 	       PkgIterator DepPkg = Ver.ParentPkg();
 
 
 	       // Check if the version that is going to be installed will satisfy the dependency
 	       // Check if the version that is going to be installed will satisfy the dependency
-	       if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false)
+	       if (Cache[DepPkg].InstallVer != *I)
 		  continue;
 		  continue;
 
 
-	       if (PkgLoop == true)
-	       {
-		  if (Debug)
-		     std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
-	          Bad = false;
-		  break;
-	       }
-	       else
+	       if (List->IsFlag(DepPkg,pkgOrderList::UnPacked))
 	       {
 	       {
-		  if (Debug)
-		     clog << OutputInDepth(Depth) << "Unpacking " << DepPkg.FullName() << " to avoid loop " << Cur << endl;
+		  if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop)
+		  {
+		    // This dependency has already been dealt with by another SmartConfigure on Pkg
+		    Bad = false;
+		    break;
+		  }
+		  /* Check for a loop to prevent one forming
+		       If A depends on B and B depends on A, SmartConfigure will
+		       just hop between them if this is not checked. Dont remove the
+		       loop flag after finishing however as loop is already set.
+		       This means that there is another SmartConfigure call for this
+		       package and it will remove the loop flag */
 		  if (PkgLoop == false)
 		  if (PkgLoop == false)
 		     List->Flag(Pkg,pkgOrderList::Loop);
 		     List->Flag(Pkg,pkgOrderList::Loop);
-		  if (SmartUnPack(DepPkg, true, Depth + 1) == true)
+		  if (SmartConfigure(DepPkg, Depth + 1) == true)
 		  {
 		  {
 		     Bad = false;
 		     Bad = false;
 		     if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
 		     if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
-		        Changed = true;
+			Changed = true;
 		  }
 		  }
 		  if (PkgLoop == false)
 		  if (PkgLoop == false)
-		     List->RmFlag(Pkg,pkgOrderList::Loop);
+		    List->RmFlag(Pkg,pkgOrderList::Loop);
+		  // If SmartConfigure was succesfull, Bad is false, so break
 		  if (Bad == false)
 		  if (Bad == false)
 		     break;
 		     break;
 	       }
 	       }
+	       else if (List->IsFlag(DepPkg,pkgOrderList::Configured))
+	       {
+		  Bad = false;
+		  break;
+	       }
 	    }
 	    }
-
-	    if (Cur == End)
+	    if (Cur == End || Bad == false)
 	       break;
 	       break;
-	 }
+         }
+
 
 
 	 if (Bad == true && Changed == false && Debug == true)
 	 if (Bad == true && Changed == false && Debug == true)
-	    std::clog << OutputInDepth(Depth) << "Could not satisfy " << Start << std::endl;
+	    std::clog << OutputInDepth(Depth) << "Could not satisfy " << *D << std::endl;
       }
       }
       if (i++ > max_loops)
       if (i++ > max_loops)
-         return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack for %s, aborting", Pkg.FullName().c_str());
+         return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (2) for %s, aborting", Pkg.FullName().c_str());
    } while (Changed == true);
    } while (Changed == true);
    
    
    if (Bad) {
    if (Bad) {
@@ -603,7 +628,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
       This will be either dealt with if the package is configured as a dependency of Pkg (if and when Pkg is configured),
       This will be either dealt with if the package is configured as a dependency of Pkg (if and when Pkg is configured),
       or by the ConfigureAll call at the end of the for loop in OrderInstall. */
       or by the ConfigureAll call at the end of the for loop in OrderInstall. */
    bool Changed = false;
    bool Changed = false;
-   const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 500);
+   const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 5000);
    unsigned int i = 0;
    unsigned int i = 0;
    do 
    do 
    {
    {

+ 12 - 0
apt-pkg/pkgcache.cc

@@ -924,6 +924,18 @@ string pkgCache::VerIterator::RelStr() const
    return Res;
    return Res;
 }
 }
 									/*}}}*/
 									/*}}}*/
+// VerIterator::MultiArchType - string representing MultiArch flag	/*{{{*/
+const char * pkgCache::VerIterator::MultiArchType() const
+{
+   if ((S->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same)
+      return "same";
+   else if ((S->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
+      return "foreign";
+   else if ((S->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
+      return "allowed";
+   return "none";
+}
+									/*}}}*/
 // PkgFileIterator::IsOk - Checks if the cache is in sync with the file	/*{{{*/
 // PkgFileIterator::IsOk - Checks if the cache is in sync with the file	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This stats the file and compares its stats with the ones that were
 /* This stats the file and compares its stats with the ones that were

+ 3 - 1
apt-pkg/pkgcachegen.cc

@@ -296,6 +296,8 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator
 
 
    // Find the right version to write the description
    // Find the right version to write the description
    MD5SumValue CurMd5 = List.Description_md5();
    MD5SumValue CurMd5 = List.Description_md5();
+   if (CurMd5.Value().empty() == true || List.Description().empty() == true)
+      return true;
    std::string CurLang = List.DescriptionLanguage();
    std::string CurLang = List.DescriptionLanguage();
 
 
    for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
    for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
@@ -480,7 +482,7 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator
 
 
    /* Record the Description (it is not translated) */
    /* Record the Description (it is not translated) */
    MD5SumValue CurMd5 = List.Description_md5();
    MD5SumValue CurMd5 = List.Description_md5();
-   if (CurMd5.Value().empty() == true)
+   if (CurMd5.Value().empty() == true || List.Description().empty() == true)
       return true;
       return true;
    std::string CurLang = List.DescriptionLanguage();
    std::string CurLang = List.DescriptionLanguage();
 
 

+ 18 - 7
apt-pkg/policy.cc

@@ -166,11 +166,15 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk
       tracks the default when the default is taken away, and a permanent
       tracks the default when the default is taken away, and a permanent
       pin that stays at that setting.
       pin that stays at that setting.
     */
     */
+   bool PrefSeen = false;
    for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
    for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
    {
    {
       /* Lets see if this version is the installed version */
       /* Lets see if this version is the installed version */
       bool instVer = (Pkg.CurrentVer() == Ver);
       bool instVer = (Pkg.CurrentVer() == Ver);
 
 
+      if (Pref == Ver)
+	 PrefSeen = true;
+
       for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF)
       for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF)
       {
       {
 	 /* If this is the status file, and the current version is not the
 	 /* If this is the status file, and the current version is not the
@@ -187,26 +191,33 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk
 	 {
 	 {
 	    Pref = Ver;
 	    Pref = Ver;
 	    Max = Prio;
 	    Max = Prio;
+	    PrefSeen = true;
 	 }
 	 }
 	 if (Prio > MaxAlt)
 	 if (Prio > MaxAlt)
 	 {
 	 {
 	    PrefAlt = Ver;
 	    PrefAlt = Ver;
 	    MaxAlt = Prio;
 	    MaxAlt = Prio;
-	 }	 
-      }      
-      
+	 }
+      }
+
       if (instVer == true && Max < 1000)
       if (instVer == true && Max < 1000)
       {
       {
+	 /* Not having seen the Pref yet means we have a specific pin below 1000
+	    on a version below the current installed one, so ignore the specific pin
+	    as this would be a downgrade otherwise */
+	 if (PrefSeen == false || Pref.end() == true)
+	 {
+	    Pref = Ver;
+	    PrefSeen = true;
+	 }
 	 /* Elevate our current selection (or the status file itself)
 	 /* Elevate our current selection (or the status file itself)
 	    to the Pseudo-status priority. */
 	    to the Pseudo-status priority. */
-	 if (Pref.end() == true)
-	    Pref = Ver;
 	 Max = 1000;
 	 Max = 1000;
-	 
+
 	 // Fast path optimize.
 	 // Fast path optimize.
 	 if (StatusOverride == false)
 	 if (StatusOverride == false)
 	    break;
 	    break;
-      }            
+      }
    }
    }
    // If we do not find our candidate, use the one with the highest pin.
    // If we do not find our candidate, use the one with the highest pin.
    // This means that if there is a version available with pin > 0; there
    // This means that if there is a version available with pin > 0; there

+ 1 - 1
apt-pkg/tagfile.h

@@ -84,7 +84,7 @@ class pkgTagSection
       Stop = this->Stop;
       Stop = this->Stop;
    };
    };
    
    
-   pkgTagSection() : Section(0), TagCount(0), Stop(0) {};
+   pkgTagSection() : Section(0), TagCount(0), d(NULL), Stop(0) {};
    virtual ~pkgTagSection() {};
    virtual ~pkgTagSection() {};
 };
 };
 
 

+ 1 - 1
apt-pkg/vendorlist.cc

@@ -66,7 +66,7 @@ bool pkgVendorList::CreateList(Configuration& Cnf)			/*{{{*/
       Configuration Block(Top);
       Configuration Block(Top);
       string VendorID = Top->Tag;
       string VendorID = Top->Tag;
       vector <struct Vendor::Fingerprint *> *Fingerprints = new vector<Vendor::Fingerprint *>;
       vector <struct Vendor::Fingerprint *> *Fingerprints = new vector<Vendor::Fingerprint *>;
-      struct Vendor::Fingerprint *Fingerprint = new struct Vendor::Fingerprint;
+      struct Vendor::Fingerprint *Fingerprint = new struct Vendor::Fingerprint();
       string Origin = Block.Find("Origin");
       string Origin = Block.Find("Origin");
 
 
       Fingerprint->Print = Block.Find("Fingerprint");
       Fingerprint->Print = Block.Find("Fingerprint");

+ 1 - 0
buildlib/apti18n.h.in

@@ -25,4 +25,5 @@
 # define _(x) x
 # define _(x) x
 # define P_(msg,plural,n) (n == 1 ? msg : plural)
 # define P_(msg,plural,n) (n == 1 ? msg : plural)
 # define N_(x) x
 # define N_(x) x
+# define dgettext(d, m) m
 #endif
 #endif

+ 2 - 2
buildlib/configure.mak

@@ -2,7 +2,7 @@
 
 
 # This make fragment is included by the toplevel make to handle configure
 # This make fragment is included by the toplevel make to handle configure
 # and setup. It defines a target called startup that when run will init
 # and setup. It defines a target called startup that when run will init
-# the build directory, generate configure from configure.in, create aclocal
+# the build directory, generate configure from configure.ac, create aclocal
 # and has rules to run config.status should one of the .in files change.
 # and has rules to run config.status should one of the .in files change.
 
 
 # Input
 # Input
@@ -48,7 +48,7 @@ missing-config-files:
 	@echo "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD"
 	@echo "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD"
 	exit 100
 	exit 100
 
 
-configure: aclocal.m4 configure.in buildlib/config.guess buildlib/config.sub
+configure: aclocal.m4 configure.ac buildlib/config.guess buildlib/config.sub
 	autoconf
 	autoconf
 
 
 aclocal.m4: $(wildcard buildlib/*.m4)
 aclocal.m4: $(wildcard buildlib/*.m4)

+ 1 - 1
buildlib/copy.mak

@@ -21,7 +21,7 @@ veryclean: veryclean/$(LOCAL)
 
 
 MKDIRS += $(dir $($(LOCAL)-LIST))
 MKDIRS += $(dir $($(LOCAL)-LIST))
 
 
-$($(LOCAL)-LIST) : $(TO)/% : % dirs
+$($(LOCAL)-LIST) : $(TO)/% : %
 	echo Installing $< to $(@D)
 	echo Installing $< to $(@D)
 	cp $< $(@D)
 	cp $< $(@D)
 
 

+ 8 - 9
buildlib/defaults.mak

@@ -172,12 +172,11 @@ ifeq ($(NUM_PROCS),1)
   PARALLEL_RUN=no
   PARALLEL_RUN=no
 endif
 endif
 
 
-# mvo: commented out, lead to build failures in the arch-build target
-#ifndef PARALLEL_RUN
-# PARALLEL_RUN=yes
-# .EXPORT: PARALLEL_RUN
-# # handle recursion
-# ifneq ($(NUM_PROCS),)
-#  MAKEFLAGS += -j $(NUM_PROCS)
-# endif
-#endif
+ifndef PARALLEL_RUN
+ PARALLEL_RUN=yes
+ export PARALLEL_RUN
+ # handle recursion
+ ifneq ($(NUM_PROCS),)
+  MAKEFLAGS += -j $(NUM_PROCS)
+ endif
+endif

+ 2 - 2
buildlib/library.mak

@@ -51,7 +51,7 @@ $(LIB)/lib$(LIBRARY).so: $(LIB)/lib$(LIBRARY).so.$(MAJOR).$(MINOR)
 	ln -sf $(<F) $@
 	ln -sf $(<F) $@
 
 
 # The binary build rule
 # The binary build rule
-$(LIB)/lib$(LIBRARY).so.$(MAJOR).$(MINOR): $($(LOCAL)-HEADERS) $($(LOCAL)-OBJS)
+$(LIB)/lib$(LIBRARY).so.$(MAJOR).$(MINOR): $($(LOCAL)-HEADERS) $($(LOCAL)-OBJS) $(LIBRARYDEPENDS)
 	-rm -f $(LIB)/lib$($(@F)-LIBRARY)*.so* 2> /dev/null
 	-rm -f $(LIB)/lib$($(@F)-LIBRARY)*.so* 2> /dev/null
 	echo Building shared library $@
 	echo Building shared library $@
 	$(CXX) $(CXXFLAGS) $(LDFLAGS) $(PICFLAGS) $(LFLAGS) $(LFLAGS_SO)\
 	$(CXX) $(CXXFLAGS) $(LDFLAGS) $(PICFLAGS) $(LFLAGS) $(LFLAGS_SO)\
@@ -61,7 +61,7 @@ $(LIB)/lib$(LIBRARY).so.$(MAJOR).$(MINOR): $($(LOCAL)-HEADERS) $($(LOCAL)-OBJS)
 
 
 # Compilation rules
 # Compilation rules
 vpath %.cc $(SUBDIRS)
 vpath %.cc $(SUBDIRS)
-$(OBJ)/%.opic: %.cc
+$(OBJ)/%.opic: %.cc $(LIBRARYDEPENDS)
 	echo Compiling $< to $@
 	echo Compiling $< to $@
 	$(CXX) -c $(INLINEDEPFLAG) $(CPPFLAGS) $(CXXFLAGS) $(PICFLAGS) -o $@ $<
 	$(CXX) -c $(INLINEDEPFLAG) $(CPPFLAGS) $(CXXFLAGS) $(PICFLAGS) -o $@ $<
 	$(DoDep)
 	$(DoDep)

+ 7 - 5
buildlib/po4a_manpage.mak

@@ -25,6 +25,7 @@ $(LOCAL)-LIST := $(SOURCE)
 
 
 # Install generation hooks
 # Install generation hooks
 manpages: $($(LOCAL)-LIST)
 manpages: $($(LOCAL)-LIST)
+clean: clean/$(LOCAL)
 veryclean: veryclean/$(LOCAL)
 veryclean: veryclean/$(LOCAL)
 
 
 apt-verbatim.ent: ../apt-verbatim.ent
 apt-verbatim.ent: ../apt-verbatim.ent
@@ -37,15 +38,16 @@ manpage-style.xsl: ../manpage-style.xsl
 $($(LOCAL)-LIST) :: % : %.xml $(STYLESHEET) $(INCLUDES)
 $($(LOCAL)-LIST) :: % : %.xml $(STYLESHEET) $(INCLUDES)
 	echo Creating man page $@
 	echo Creating man page $@
 	$(XSLTPROC) -o $@ $(STYLESHEET) $< || exit 200 # why xsltproc doesn't respect the -o flag here???
 	$(XSLTPROC) -o $@ $(STYLESHEET) $< || exit 200 # why xsltproc doesn't respect the -o flag here???
-	test -f $(subst .$(LC),,$@) || echo FIXME: xsltproc respect the -o flag now, workaround can be removed
+	test -f $(subst .$(LC),,$@) || echo 'FIXME: xsltproc respects the -o flag now, workaround can be removed'
 	mv -f $(subst .$(LC),,$@) $@
 	mv -f $(subst .$(LC),,$@) $@
 
 
 # Clean rule
 # Clean rule
-.PHONY: veryclean/$(LOCAL)
+.PHONY: clean/$(LOCAL) veryclean/$(LOCAL)
+clean/$(LOCAL):
+	rm -f $($(@F)-LIST) apt.ent apt-verbatim.ent
 veryclean/$(LOCAL):
 veryclean/$(LOCAL):
-	-rm -rf $($(@F)-LIST) apt.ent apt-verbatim.ent apt.$(LC).8 \
-		$(addsuffix .xml,$($(@F)-LIST)) \
-		offline.$(LC).sgml guide.$(LC).sgml
+	# we are nuking the directory we are working in as it is auto-generated
+	rm -rf $(shell readlink -f .)
 
 
 HAVE_PO4A=yes
 HAVE_PO4A=yes
 endif
 endif

+ 6 - 1
buildlib/podomain.mak

@@ -4,6 +4,8 @@
 # declared domain of the make file. It also arranges to set the DOMAIN 
 # declared domain of the make file. It also arranges to set the DOMAIN 
 # CPPFLAG for the compilation.
 # CPPFLAG for the compilation.
 
 
+ifneq ($(APT_DOMAIN),none)
+
 MY_DOMAIN := $(PACKAGE)
 MY_DOMAIN := $(PACKAGE)
 ifdef APT_DOMAIN
 ifdef APT_DOMAIN
 $($(LOCAL)-OBJS): CPPFLAGS := $(CPPFLAGS) -DAPT_DOMAIN='"$(APT_DOMAIN)"'
 $($(LOCAL)-OBJS): CPPFLAGS := $(CPPFLAGS) -DAPT_DOMAIN='"$(APT_DOMAIN)"'
@@ -13,10 +15,13 @@ endif
 MKDIRS += $(PO_DOMAINS)/$(MY_DOMAIN)
 MKDIRS += $(PO_DOMAINS)/$(MY_DOMAIN)
 $(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list: SRC := $(addprefix $(SUBDIR)/,$(SOURCE))
 $(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list: SRC := $(addprefix $(SUBDIR)/,$(SOURCE))
 $(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list: makefile dirs
 $(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list: makefile dirs
-	(echo $(SRC) | xargs -n1 echo) > $@
+	(echo $(SRC) | xargs -n1 echo) > $@.tmp
+	cmp --silent $@.tmp $@ || mv $@.tmp $@
 startup binary program clean update-po: $(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list
 startup binary program clean update-po: $(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list
 
 
 veryclean: veryclean/$(LOCAL)
 veryclean: veryclean/$(LOCAL)
 veryclean/po/$(LOCAL): LIST := $(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list
 veryclean/po/$(LOCAL): LIST := $(PO_DOMAINS)/$(MY_DOMAIN)/$(LOCAL).$(TYPE)list
 veryclean/po/$(LOCAL):
 veryclean/po/$(LOCAL):
 	rm -f $(LIST)
 	rm -f $(LIST)
+
+endif

+ 123 - 53
cmdline/apt-cache.cc

@@ -1127,6 +1127,24 @@ bool Dotty(CommandLine &CmdL)
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This displays the package record from the proper package index file. 
 /* This displays the package record from the proper package index file. 
    It is not used by DumpAvail for performance reasons. */
    It is not used by DumpAvail for performance reasons. */
+
+static unsigned char const* skipDescriptionFields(unsigned char const * DescP)
+{
+   char const * const TagName = "\nDescription";
+   size_t const TagLen = strlen(TagName);
+   while ((DescP = (unsigned char*)strchr((char*)DescP, '\n')) != NULL)
+   {
+      if (DescP[1] == ' ')
+	 DescP += 2;
+      else if (strncmp((char*)DescP, TagName, TagLen) == 0)
+	 DescP += TagLen;
+      else
+	 break;
+   }
+   if (DescP != NULL)
+      ++DescP;
+   return DescP;
+}
 bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
 bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
 {
 {
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgCache *Cache = CacheFile.GetPkgCache();
@@ -1150,21 +1168,27 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
    if (PkgF.Open(I.FileName(), FileFd::ReadOnly, FileFd::Extension) == false)
    if (PkgF.Open(I.FileName(), FileFd::ReadOnly, FileFd::Extension) == false)
       return false;
       return false;
 
 
-   // Read the record
-   unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+1];
-   Buffer[V.FileList()->Size] = '\n';
-   if (PkgF.Seek(V.FileList()->Offset) == false ||
-       PkgF.Read(Buffer,V.FileList()->Size) == false)
+   // Read the record (and ensure that it ends with a newline and NUL)
+   unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+2];
+   Buffer[Vf->Size] = '\n';
+   Buffer[Vf->Size+1] = '\0';
+   if (PkgF.Seek(Vf->Offset) == false ||
+       PkgF.Read(Buffer,Vf->Size) == false)
    {
    {
       delete [] Buffer;
       delete [] Buffer;
       return false;
       return false;
    }
    }
 
 
    // Get a pointer to start of Description field
    // Get a pointer to start of Description field
-   const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "Description:");
+   const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "\nDescription");
+   if (DescP != NULL)
+      ++DescP;
+   else
+      DescP = Buffer + Vf->Size;
 
 
    // Write all but Description
    // Write all but Description
-   if (fwrite(Buffer,1,DescP - Buffer,stdout) < (size_t)(DescP - Buffer))
+   size_t const length = DescP - Buffer;
+   if (length != 0 && FileFd::Write(STDOUT_FILENO, Buffer, length) == false)
    {
    {
       delete [] Buffer;
       delete [] Buffer;
       return false;
       return false;
@@ -1173,29 +1197,44 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
    // Show the right description
    // Show the right description
    pkgRecords Recs(*Cache);
    pkgRecords Recs(*Cache);
    pkgCache::DescIterator Desc = V.TranslatedDescription();
    pkgCache::DescIterator Desc = V.TranslatedDescription();
-   pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
-   cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
+   if (Desc.end() == false)
+   {
+      pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
+      cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
+      cout << std::endl << "Description-md5: " << Desc.md5() << std::endl;
+
+      // Find the first field after the description (if there is any)
+      DescP = skipDescriptionFields(DescP);
+   }
+   // else we have no translation, so we found a lonely Description-md5 -> don't skip it
 
 
-   // Find the first field after the description (if there is any)
-   for(DescP++;DescP != &Buffer[V.FileList()->Size];DescP++) 
+   // write the rest of the buffer, but skip mixed in Descriptions* fields
+   while (DescP != NULL)
    {
    {
-      if(*DescP == '\n' && *(DescP+1) != ' ') 
+      const unsigned char * const Start = DescP;
+      const unsigned char *End = (unsigned char*)strstr((char*)DescP, "\nDescription");
+      if (End == NULL)
       {
       {
-	 // write the rest of the buffer
-	 const unsigned char *end=&Buffer[V.FileList()->Size];
-	 if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP)) 
-	 {
-	    delete [] Buffer;
-	    return false;
-	 }
-
-	 break;
+	 End = &Buffer[Vf->Size];
+	 DescP = NULL;
+      }
+      else
+      {
+	 ++End; // get the newline into the output
+	 DescP = skipDescriptionFields(End + strlen("Description"));
+      }
+      size_t const length = End - Start;
+      if (length != 0 && FileFd::Write(STDOUT_FILENO, Start, length) == false)
+      {
+	 delete [] Buffer;
+	 return false;
       }
       }
    }
    }
-   // write a final newline (after the description)
+
+   // write a final newline after the last field
    cout<<endl;
    cout<<endl;
-   delete [] Buffer;
 
 
+   delete [] Buffer;
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1203,7 +1242,7 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
 struct ExDescFile
 struct ExDescFile
 {
 {
    pkgCache::DescFile *Df;
    pkgCache::DescFile *Df;
-   bool NameMatch;
+   map_ptrloc ID;
 };
 };
 
 
 // Search - Perform a search						/*{{{*/
 // Search - Perform a search						/*{{{*/
@@ -1246,37 +1285,52 @@ bool Search(CommandLine &CmdL)
       return false;
       return false;
    }
    }
    
    
-   ExDescFile *DFList = new ExDescFile[Cache->HeaderP->GroupCount+1];
-   memset(DFList,0,sizeof(*DFList)*Cache->HeaderP->GroupCount+1);
+   size_t const descCount = Cache->HeaderP->GroupCount + 1;
+   ExDescFile *DFList = new ExDescFile[descCount];
+   memset(DFList,0,sizeof(*DFList) * descCount);
+
+   bool PatternMatch[descCount * NumPatterns];
+   memset(PatternMatch,false,sizeof(PatternMatch));
 
 
    // Map versions that we want to write out onto the VerList array.
    // Map versions that we want to write out onto the VerList array.
    for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
    for (pkgCache::GrpIterator G = Cache->GrpBegin(); G.end() == false; ++G)
    {
    {
-      if (DFList[G->ID].NameMatch == true)
-	 continue;
-
-      DFList[G->ID].NameMatch = true;
-      for (unsigned I = 0; I != NumPatterns; I++)
+      size_t const PatternOffset = G->ID * NumPatterns;
+      size_t unmatched = 0, matched = 0;
+      for (unsigned I = 0; I < NumPatterns; ++I)
       {
       {
-	 if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
-	    continue;
-	 DFList[G->ID].NameMatch = false;
-	 break;
+	 if (PatternMatch[PatternOffset + I] == true)
+	    ++matched;
+	 else if (regexec(&Patterns[I],G.Name(),0,0,0) == 0)
+	    PatternMatch[PatternOffset + I] = true;
+	 else
+	    ++unmatched;
       }
       }
-        
-      // Doing names only, drop any that dont match..
-      if (NamesOnly == true && DFList[G->ID].NameMatch == false)
+
+      // already dealt with this package?
+      if (matched == NumPatterns)
 	 continue;
 	 continue;
-	 
+
+      // Doing names only, drop any that don't match..
+      if (NamesOnly == true && unmatched == NumPatterns)
+	 continue;
+
       // Find the proper version to use
       // Find the proper version to use
       pkgCache::PkgIterator P = G.FindPreferredPkg();
       pkgCache::PkgIterator P = G.FindPreferredPkg();
       if (P.end() == true)
       if (P.end() == true)
 	 continue;
 	 continue;
       pkgCache::VerIterator V = Plcy->GetCandidateVer(P);
       pkgCache::VerIterator V = Plcy->GetCandidateVer(P);
       if (V.end() == false)
       if (V.end() == false)
-	 DFList[G->ID].Df = V.TranslatedDescription().FileList();
+      {
+	 pkgCache::DescIterator const D = V.TranslatedDescription();
+	 //FIXME: packages without a description can't be found
+	 if (D.end() == true)
+	    continue;
+	 DFList[G->ID].Df = D.FileList();
+	 DFList[G->ID].ID = G->ID;
+      }
 
 
-      if (DFList[G->ID].NameMatch == false)
+      if (unmatched == NumPatterns)
 	 continue;
 	 continue;
 
 
       // Include all the packages that provide matching names too
       // Include all the packages that provide matching names too
@@ -1287,34 +1341,50 @@ bool Search(CommandLine &CmdL)
 	    continue;
 	    continue;
 
 
 	 unsigned long id = Prv.OwnerPkg().Group()->ID;
 	 unsigned long id = Prv.OwnerPkg().Group()->ID;
-	 DFList[id].Df = V.TranslatedDescription().FileList();
-	 DFList[id].NameMatch = true;
+	 pkgCache::DescIterator const D = V.TranslatedDescription();
+	 //FIXME: packages without a description can't be found
+	 if (D.end() == true)
+	    continue;
+	 DFList[id].Df = D.FileList();
+	 DFList[id].ID = id;
+
+	 size_t const PrvPatternOffset = id * NumPatterns;
+	 for (unsigned I = 0; I < NumPatterns; ++I)
+	    PatternMatch[PrvPatternOffset + I] = PatternMatch[PatternOffset + I];
       }
       }
    }
    }
-   
+
    LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList));
    LocalitySort(&DFList->Df,Cache->HeaderP->GroupCount,sizeof(*DFList));
 
 
    // Create the text record parser
    // Create the text record parser
    pkgRecords Recs(*Cache);
    pkgRecords Recs(*Cache);
    // Iterate over all the version records and check them
    // Iterate over all the version records and check them
-   for (ExDescFile *J = DFList; J->Df != 0; J++)
+   for (ExDescFile *J = DFList; J->Df != 0; ++J)
    {
    {
       pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df));
       pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(*Cache,J->Df));
+      size_t const PatternOffset = J->ID * NumPatterns;
 
 
-      if (J->NameMatch == false && NamesOnly == false)
+      if (NamesOnly == false)
       {
       {
 	 string const LongDesc = P.LongDesc();
 	 string const LongDesc = P.LongDesc();
-	 J->NameMatch = true;
-	 for (unsigned I = 0; I != NumPatterns; I++)
+	 for (unsigned I = 0; I < NumPatterns; ++I)
 	 {
 	 {
-	    if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
+	    if (PatternMatch[PatternOffset + I] == true)
 	       continue;
 	       continue;
-	    J->NameMatch = false;
-	    break;
+	    else if (regexec(&Patterns[I],LongDesc.c_str(),0,0,0) == 0)
+	       PatternMatch[PatternOffset + I] = true;
 	 }
 	 }
       }
       }
-      
-      if (J->NameMatch == true)
+
+      bool matchedAll = true;
+      for (unsigned I = 0; I < NumPatterns; ++I)
+	 if (PatternMatch[PatternOffset + I] == false)
+	 {
+	    matchedAll = false;
+	    break;
+	 }
+
+      if (matchedAll == true)
       {
       {
 	 if (ShowFull == true)
 	 if (ShowFull == true)
 	 {
 	 {

+ 22 - 12
cmdline/apt-cdrom.cc

@@ -39,6 +39,12 @@
 
 
 #include <apti18n.h>
 #include <apti18n.h>
 									/*}}}*/
 									/*}}}*/
+static const char *W_NO_CDROM_FOUND = \
+   N_("No CD-ROM could be auto-detected or found using "
+      "the default mount point.\n"
+      "You may try the --cdrom option to set the CD-ROM mount point. "
+      "See 'man apt-cdrom' for more "
+      "information about the CD-ROM auto-detection and mount point.");
 
 
 using namespace std;
 using namespace std;
 
 
@@ -60,7 +66,9 @@ void pkgCdromTextStatus::Prompt(const char *Text)
 {
 {
    char C;
    char C;
    cout << Text << ' ' << flush;
    cout << Text << ' ' << flush;
-   read(STDIN_FILENO,&C,1);
+   if (read(STDIN_FILENO,&C,1) < 0)
+      _error->Errno("pkgCdromTextStatus::Prompt", 
+                    "Failed to read from standard input (not a terminal?)");
    if (C != '\n')
    if (C != '\n')
       cout << endl;
       cout << endl;
 }
 }
@@ -135,7 +143,6 @@ bool AutoDetectCdrom(pkgUdevCdromDevices &UdevCdroms, unsigned int &i)
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
-
 // DoAdd - Add a new CDROM						/*{{{*/
 // DoAdd - Add a new CDROM						/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This does the main add bit.. We show some status and things. The
 /* This does the main add bit.. We show some status and things. The
@@ -150,13 +157,15 @@ bool DoAdd(CommandLine &)
    bool res = true;
    bool res = true;
 
 
    bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect", true);
    bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect", true);
+   unsigned int count = 0;
    if (AutoDetect && UdevCdroms.Dlopen())
    if (AutoDetect && UdevCdroms.Dlopen())
-   {
-      unsigned int count = 0;
       while (AutoDetectCdrom(UdevCdroms, count))
       while (AutoDetectCdrom(UdevCdroms, count))
 	 res &= cdrom.Add(&log);
 	 res &= cdrom.Add(&log);
-   } else {
+   if (count == 0) {
       res = cdrom.Add(&log);
       res = cdrom.Add(&log);
+      if (res == false) {
+         _error->Error("%s", _(W_NO_CDROM_FOUND));
+      }
    }
    }
 
 
    if(res)
    if(res)
@@ -178,15 +187,16 @@ bool DoIdent(CommandLine &)
 
 
    bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect");
    bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect");
 
 
+   unsigned int count = 0;
    if (AutoDetect && UdevCdroms.Dlopen())
    if (AutoDetect && UdevCdroms.Dlopen())
-   {
-      unsigned int count = 0;
       while (AutoDetectCdrom(UdevCdroms, count))
       while (AutoDetectCdrom(UdevCdroms, count))
 	 res &= cdrom.Ident(ident, &log);
 	 res &= cdrom.Ident(ident, &log);
-   } else {
-      return cdrom.Ident(ident, &log);
+   if (count == 0) {
+      res = cdrom.Ident(ident, &log);
+      if (res == false) {
+         _error->Error("%s", _(W_NO_CDROM_FOUND));
+      }
    }
    }
- 
    return res;
    return res;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -218,7 +228,7 @@ int ShowHelp()
       "  -m   No mounting\n"
       "  -m   No mounting\n"
       "  -f   Fast mode, don't check package files\n"
       "  -f   Fast mode, don't check package files\n"
       "  -a   Thorough scan mode\n"
       "  -a   Thorough scan mode\n"
-      "  --auto-detect Auto detect drive and mount point\n"
+      "  --no-auto-detect Do not try to auto detect drive and mount point\n"
       "  -c=? Read this configuration file\n"
       "  -c=? Read this configuration file\n"
       "  -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
       "  -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
       "See fstab(5)\n";
       "See fstab(5)\n";
@@ -229,7 +239,7 @@ int main(int argc,const char *argv[])					/*{{{*/
 {
 {
    CommandLine::Args Args[] = {
    CommandLine::Args Args[] = {
       {'h',"help","help",0},
       {'h',"help","help",0},
-      {  0,"auto-detect","Acquire::cdrom::AutoDetect",0},
+      {  0,"auto-detect","Acquire::cdrom::AutoDetect", CommandLine::Boolean},
       {'v',"version","version",0},
       {'v',"version","version",0},
       {'d',"cdrom","Acquire::cdrom::mount",CommandLine::HasArg},
       {'d',"cdrom","Acquire::cdrom::mount",CommandLine::HasArg},
       {'r',"rename","APT::CDROM::Rename",0},
       {'r',"rename","APT::CDROM::Rename",0},

+ 39 - 10
cmdline/apt-get.cc

@@ -130,13 +130,42 @@ class CacheFile : public pkgCacheFile
 /* Returns true on a Yes.*/
 /* Returns true on a Yes.*/
 bool YnPrompt(bool Default=true)
 bool YnPrompt(bool Default=true)
 {
 {
+   /* nl_langinfo does not support LANGUAGE setting, so we unset it here
+      to have the help-message (hopefully) match the expected characters */
+   char * language = getenv("LANGUAGE");
+   if (language != NULL)
+      language = strdup(language);
+   if (language != NULL)
+      unsetenv("LANGUAGE");
+
+   if (Default == true)
+      // TRANSLATOR: Yes/No question help-text: defaulting to Y[es]
+      //             e.g. "Do you want to continue? [Y/n] "
+      //             The user has to answer with an input matching the
+      //             YESEXPR/NOEXPR defined in your l10n.
+      c2out << " " << _("[Y/n]") << " " << std::flush;
+   else
+      // TRANSLATOR: Yes/No question help-text: defaulting to N[o]
+      //             e.g. "Should this file be removed? [y/N] "
+      //             The user has to answer with an input matching the
+      //             YESEXPR/NOEXPR defined in your l10n.
+      c2out << " " << _("[y/N]") << " " << std::flush;
+
+   if (language != NULL)
+   {
+      setenv("LANGUAGE", language, 0);
+      free(language);
+   }
+
    if (_config->FindB("APT::Get::Assume-Yes",false) == true)
    if (_config->FindB("APT::Get::Assume-Yes",false) == true)
    {
    {
+      // TRANSLATOR: "Yes" answer printed for a yes/no question if --assume-yes is set
       c1out << _("Y") << endl;
       c1out << _("Y") << endl;
       return true;
       return true;
    }
    }
    else if (_config->FindB("APT::Get::Assume-No",false) == true)
    else if (_config->FindB("APT::Get::Assume-No",false) == true)
    {
    {
+      // TRANSLATOR: "No" answer printed for a yes/no question if --assume-no is set
       c1out << _("N") << endl;
       c1out << _("N") << endl;
       return false;
       return false;
    }
    }
@@ -1076,7 +1105,7 @@ static bool CheckAuth(pkgAcquire& Fetcher)
    if (_config->FindI("quiet",0) < 2
    if (_config->FindI("quiet",0) < 2
        && _config->FindB("APT::Get::Assume-Yes",false) == false)
        && _config->FindB("APT::Get::Assume-Yes",false) == false)
    {
    {
-      c2out << _("Install these packages without verification [y/N]? ") << flush;
+      c2out << _("Install these packages without verification?") << flush;
       if (!YnPrompt(false))
       if (!YnPrompt(false))
          return _error->Error(_("Some packages could not be authenticated"));
          return _error->Error(_("Some packages could not be authenticated"));
 
 
@@ -1281,8 +1310,8 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
 	 if (_config->FindI("quiet",0) < 2 &&
 	 if (_config->FindI("quiet",0) < 2 &&
 	     _config->FindB("APT::Get::Assume-Yes",false) == false)
 	     _config->FindB("APT::Get::Assume-Yes",false) == false)
 	 {
 	 {
-	    c2out << _("Do you want to continue [Y/n]? ") << flush;
-	 
+	    c2out << _("Do you want to continue?") << flush;
+
 	    if (YnPrompt() == false)
 	    if (YnPrompt() == false)
 	    {
 	    {
 	       c2out << _("Abort.") << endl;
 	       c2out << _("Abort.") << endl;
@@ -1965,7 +1994,6 @@ bool DoInstall(CommandLine &CmdL)
       if (Fix != NULL)
       if (Fix != NULL)
       {
       {
 	 // Call the scored problem resolver
 	 // Call the scored problem resolver
-	 Fix->InstallProtect();
 	 Fix->Resolve(true);
 	 Fix->Resolve(true);
 	 delete Fix;
 	 delete Fix;
       }
       }
@@ -2297,9 +2325,10 @@ bool DoClean(CommandLine &CmdL)
    FileFd Lock;
    FileFd Lock;
    if (_config->FindB("Debug::NoLocking",false) == false)
    if (_config->FindB("Debug::NoLocking",false) == false)
    {
    {
-      Lock.Fd(GetLock(archivedir + "lock"));
-      if (_error->PendingError() == true)
+      int lock_fd = GetLock(archivedir + "lock");
+      if (lock_fd < 0)
 	 return _error->Error(_("Unable to lock the download directory"));
 	 return _error->Error(_("Unable to lock the download directory"));
+      Lock.Fd(lock_fd);
    }
    }
    
    
    pkgAcquire Fetcher;
    pkgAcquire Fetcher;
@@ -2333,9 +2362,10 @@ bool DoAutoClean(CommandLine &CmdL)
    FileFd Lock;
    FileFd Lock;
    if (_config->FindB("Debug::NoLocking",false) == false)
    if (_config->FindB("Debug::NoLocking",false) == false)
    {
    {
-      Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
-      if (_error->PendingError() == true)
+      int lock_fd = GetLock(_config->FindDir("Dir::Cache::Archives") + "lock");
+      if (lock_fd < 0)
 	 return _error->Error(_("Unable to lock the download directory"));
 	 return _error->Error(_("Unable to lock the download directory"));
+      Lock.Fd(lock_fd);
    }
    }
    
    
    CacheFile Cache;
    CacheFile Cache;
@@ -3126,8 +3156,7 @@ bool DoBuildDep(CommandLine &CmdL)
             }
             }
 	 }	       
 	 }	       
       }
       }
-      
-      Fix.InstallProtect();
+
       if (Fix.Resolve(true) == false)
       if (Fix.Resolve(true) == false)
 	 _error->Discard();
 	 _error->Discard();
       
       

+ 145 - 47
cmdline/apt-key

@@ -3,27 +3,39 @@
 set -e
 set -e
 unset GREP_OPTIONS
 unset GREP_OPTIONS
 
 
-# We don't use a secret keyring, of course, but gpg panics and
-# implodes if there isn't one available
-SECRETKEYRING="$(mktemp)"
-trap "rm -f '${SECRETKEYRING}'" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
-GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring ${SECRETKEYRING}"
-
-if [ "$(id -u)" -eq 0 ]; then
-	# we could use a tmpfile here too, but creation of this tends to be time-consuming
-	eval $(apt-config shell TRUSTDBDIR Dir::Etc/d)
-	GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg"
-fi
+GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring"
+
+# gpg needs a trustdb to function, but it can't be invalid (not even empty)
+# so we create a temporary directory to store our fresh readable trustdb in
+TRUSTDBDIR="$(mktemp -d)"
+CURRENTTRAP="${CURRENTTRAP} rm -rf '${TRUSTDBDIR}';"
+trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
+chmod 700 "$TRUSTDBDIR"
+# We also don't use a secret keyring, of course, but gpg panics and
+# implodes if there isn't one available - and writeable for imports
+SECRETKEYRING="${TRUSTDBDIR}/secring.gpg"
+touch $SECRETKEYRING
+GPG_CMD="$GPG_CMD --secret-keyring $SECRETKEYRING"
+GPG_CMD="$GPG_CMD --trustdb-name ${TRUSTDBDIR}/trustdb.gpg"
+
+# now create the trustdb with an (empty) dummy keyring
+$GPG_CMD --quiet --check-trustdb --keyring $SECRETKEYRING
+# and make sure that gpg isn't trying to update the file
+GPG_CMD="$GPG_CMD --no-auto-check-trustdb --trust-model always"
 
 
 GPG="$GPG_CMD"
 GPG="$GPG_CMD"
 
 
 MASTER_KEYRING=""
 MASTER_KEYRING=""
-ARCHIVE_KEYRING_URI=""
 #MASTER_KEYRING=/usr/share/keyrings/debian-master-keyring.gpg
 #MASTER_KEYRING=/usr/share/keyrings/debian-master-keyring.gpg
+eval $(apt-config shell MASTER_KEYRING APT::Key::MasterKeyring)
+ARCHIVE_KEYRING_URI=""
 #ARCHIVE_KEYRING_URI=http://ftp.debian.org/debian/debian-archive-keyring.gpg
 #ARCHIVE_KEYRING_URI=http://ftp.debian.org/debian/debian-archive-keyring.gpg
+eval $(apt-config shell ARCHIVE_KEYRING_URI APT::Key::ArchiveKeyringURI)
 
 
 ARCHIVE_KEYRING=/usr/share/keyrings/debian-archive-keyring.gpg
 ARCHIVE_KEYRING=/usr/share/keyrings/debian-archive-keyring.gpg
+eval $(apt-config shell ARCHIVE_KEYRING APT::Key::ArchiveKeyring)
 REMOVED_KEYS=/usr/share/keyrings/debian-archive-removed-keys.gpg
 REMOVED_KEYS=/usr/share/keyrings/debian-archive-removed-keys.gpg
+eval $(apt-config shell REMOVED_KEYS APT::Key::RemovedKeys)
 
 
 requires_root() {
 requires_root() {
 	if [ "$(id -u)" -ne 0 ]; then
 	if [ "$(id -u)" -ne 0 ]; then
@@ -32,6 +44,16 @@ requires_root() {
 	fi
 	fi
 }
 }
 
 
+# gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead.
+init_keyring() {
+    for path; do
+        if ! [ -e "$path" ]; then
+            touch -- "$path"
+            chmod 0644 -- "$path"
+        fi
+    done
+}
+
 add_keys_with_verify_against_master_keyring() {
 add_keys_with_verify_against_master_keyring() {
     ADD_KEYRING=$1
     ADD_KEYRING=$1
     MASTER=$2
     MASTER=$2
@@ -129,6 +151,60 @@ update() {
     fi
     fi
 }
 }
 
 
+remove_key_from_keyring() {
+    local GPG="$GPG_CMD --keyring $1"
+    # check if the key is in this keyring: the key id is in the 5 column at the end
+    if ! $GPG --with-colons --list-keys 2>&1 | grep -q "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+$2:"; then
+	return
+    fi
+    if [ ! -w "$1" ]; then
+	echo >&2 "Key ${2} is in keyring ${1}, but can't be removed as it is read only."
+	return
+    fi
+    # check if it is the only key in the keyring and if so remove the keyring alltogether
+    if [ '1' = "$($GPG --with-colons --list-keys | grep "^pub:[^:]*:[^:]*:[^:]*:[0-9A-F]\+:" | wc -l)" ]; then
+	mv -f "$1" "${1}~" # behave like gpg
+	return
+    fi
+    # we can't just modify pointed to files as these might be in /usr or something
+    local REALTARGET
+    if [ -L "$1" ]; then
+	REALTARGET="$(readlink -f "$1")"
+	mv -f "$1" "${1}.dpkg-tmp"
+	cp -a "$REALTARGET" "$1"
+	ls "$(dirname $1)"
+    fi
+    # delete the key from the keyring
+    $GPG --batch --delete-key --yes "$2"
+    if [ -n "$REALTARGET" ]; then
+	# the real backup is the old link, not the copy we made
+	mv -f "${1}.dpkg-tmp" "${1}~"
+    fi
+}
+
+remove_key() {
+    requires_root
+
+    # if a --keyring was given, just remove from there
+    if [ -n "$FORCED_KEYRING" ]; then
+	remove_key_from_keyring "$FORCED_KEYRING" "$1"
+    else
+	# otherwise all known keyrings are up for inspection
+	local TRUSTEDFILE="/etc/apt/trusted.gpg"
+	eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring)
+	eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f)
+	remove_key_from_keyring "$TRUSTEDFILE" "$1"
+	TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
+	eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
+	if [ -d "$TRUSTEDPARTS" ]; then
+	    for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do
+		remove_key_from_keyring "$trusted" "$1"
+	    done
+	fi
+    fi
+    echo "OK"
+}
+
 
 
 usage() {
 usage() {
     echo "Usage: apt-key [--keyring file] [command] [arguments]"
     echo "Usage: apt-key [--keyring file] [command] [arguments]"
@@ -148,39 +224,54 @@ usage() {
     echo "If no specific keyring file is given the command applies to all keyring files."
     echo "If no specific keyring file is given the command applies to all keyring files."
 }
 }
 
 
-# Determine on which keyring we want to work
-if [ "$1" = "--keyring" ]; then
-        #echo "keyfile given"
-	shift
-	TRUSTEDFILE="$1"
-	if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ]; then
-		GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE"
-	else
-		echo >&2 "Error: The specified keyring »$TRUSTEDFILE« is missing or not readable"
-		exit 1
-	fi
-	shift
-# otherwise use the default
-else
-	#echo "generate list"
-	TRUSTEDFILE="/etc/apt/trusted.gpg"
-	eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring)
-	eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f)
-	if [ -r "$TRUSTEDFILE" ]; then
-		GPG="$GPG --keyring $TRUSTEDFILE"
-	fi
-	GPG="$GPG --primary-keyring $TRUSTEDFILE"
-	TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
-	eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
-	if [ -d "$TRUSTEDPARTS" ]; then
-		#echo "parts active"
-		for trusted in $(run-parts --list $TRUSTEDPARTS --regex '^.*\.gpg$'); do
-			#echo "part -> $trusted"
-			GPG="$GPG --keyring $trusted"
-		done
-	fi
+while [ -n "$1" ]; do
+   case "$1" in
+      --keyring)
+	 shift
+	 TRUSTEDFILE="$1"
+	 FORCED_KEYRING="$1"
+	 if [ -r "$TRUSTEDFILE" ] || [ "$2" = 'add' ] || [ "$2" = 'adv' ]; then
+	    GPG="$GPG --keyring $TRUSTEDFILE --primary-keyring $TRUSTEDFILE"
+	 else
+	    echo >&2 "Error: The specified keyring »$TRUSTEDFILE« is missing or not readable"
+	    exit 1
+	 fi
+	 shift
+	 ;;
+      --fakeroot)
+	 requires_root() { true; }
+	 shift
+	 ;;
+      --*)
+	 echo >&2 "Unknown option: $1"
+	 usage
+	 exit 1;;
+      *)
+	 break;;
+   esac
+done
+
+if [ -z "$TRUSTEDFILE" ]; then
+   TRUSTEDFILE="/etc/apt/trusted.gpg"
+   eval $(apt-config shell TRUSTEDFILE Apt::GPGV::TrustedKeyring)
+   eval $(apt-config shell TRUSTEDFILE Dir::Etc::Trusted/f)
+   if [ -r "$TRUSTEDFILE" ]; then
+      GPG="$GPG --keyring $TRUSTEDFILE"
+   fi
+   GPG="$GPG --primary-keyring $TRUSTEDFILE"
+   TRUSTEDPARTS="/etc/apt/trusted.gpg.d"
+   eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)
+   if [ -d "$TRUSTEDPARTS" ]; then
+      # strip / suffix as gpg will double-slash in that case (#665411)
+      STRIPPED_TRUSTEDPARTS="${TRUSTEDPARTS%/}"
+      if [ "${STRIPPED_TRUSTEDPARTS}/" = "$TRUSTEDPARTS" ]; then
+	 TRUSTEDPARTS="$STRIPPED_TRUSTEDPARTS"
+      fi
+      for trusted in $(run-parts --list "$TRUSTEDPARTS" --regex '^.*\.gpg$'); do
+	 GPG="$GPG --keyring $trusted"
+      done
+   fi
 fi
 fi
-#echo "COMMAND: $GPG"
 
 
 command="$1"
 command="$1"
 if [ -z "$command" ]; then
 if [ -z "$command" ]; then
@@ -198,33 +289,40 @@ fi
 case "$command" in
 case "$command" in
     add)
     add)
         requires_root
         requires_root
+        init_keyring "$TRUSTEDFILE"
         $GPG --quiet --batch --import "$1"
         $GPG --quiet --batch --import "$1"
         echo "OK"
         echo "OK"
         ;;
         ;;
     del|rm|remove)
     del|rm|remove)
-        requires_root
-        $GPG --quiet --batch --delete-key --yes "$1"
-        echo "OK"
+        init_keyring "$TRUSTEDFILE"
+	remove_key "$1"
         ;;
         ;;
     update)
     update)
+        init_keyring "$TRUSTEDFILE"
 	update
 	update
 	;;
 	;;
     net-update)
     net-update)
+        init_keyring "$TRUSTEDFILE"
 	net_update
 	net_update
 	;;
 	;;
     list)
     list)
+        init_keyring "$TRUSTEDFILE"
         $GPG --batch --list-keys
         $GPG --batch --list-keys
         ;;
         ;;
     finger*)
     finger*)
+        init_keyring "$TRUSTEDFILE"
         $GPG --batch --fingerprint
         $GPG --batch --fingerprint
         ;;
         ;;
     export)
     export)
+        init_keyring "$TRUSTEDFILE"
         $GPG --armor --export "$1"
         $GPG --armor --export "$1"
         ;;
         ;;
     exportall)
     exportall)
+        init_keyring "$TRUSTEDFILE"
         $GPG --armor --export
         $GPG --armor --export
         ;;
         ;;
     adv*)
     adv*)
+        init_keyring "$TRUSTEDFILE"
         echo "Executing: $GPG $*"
         echo "Executing: $GPG $*"
         $GPG $*
         $GPG $*
         ;;
         ;;

+ 2 - 2
cmdline/apt-mark.cc

@@ -202,13 +202,13 @@ bool DoHold(CommandLine &CmdL)
    if (dpkgAssertMultiArch == 0)
    if (dpkgAssertMultiArch == 0)
    {
    {
       std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory");
       std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory");
-      if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0)
-	 _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --assert-multi-arch", chrootDir.c_str());
       // redirect everything to the ultimate sink as we only need the exit-status
       // redirect everything to the ultimate sink as we only need the exit-status
       int const nullfd = open("/dev/null", O_RDONLY);
       int const nullfd = open("/dev/null", O_RDONLY);
       dup2(nullfd, STDIN_FILENO);
       dup2(nullfd, STDIN_FILENO);
       dup2(nullfd, STDOUT_FILENO);
       dup2(nullfd, STDOUT_FILENO);
       dup2(nullfd, STDERR_FILENO);
       dup2(nullfd, STDERR_FILENO);
+      if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0)
+	 _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --assert-multi-arch", chrootDir.c_str());
       execvp(Args[0], (char**) &Args[0]);
       execvp(Args[0], (char**) &Args[0]);
       _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!");
       _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!");
       _exit(2);
       _exit(2);

+ 1 - 1
cmdline/makefile

@@ -14,7 +14,7 @@ include $(PROGRAM_H)
 
 
 # The apt-get program
 # The apt-get program
 PROGRAM=apt-get
 PROGRAM=apt-get
-SLIBS = -lapt-pkg -lutil $(INTLLIBS)
+SLIBS = -lapt-pkg $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
 LIB_MAKES = apt-pkg/makefile
 SOURCE = apt-get.cc acqprogress.cc
 SOURCE = apt-get.cc acqprogress.cc
 include $(PROGRAM_H)
 include $(PROGRAM_H)

+ 3 - 7
configure.in

@@ -10,15 +10,15 @@ dnl need a C++ compiler that is semi-standard conformant, exceptions are
 dnl not used but STL is.
 dnl not used but STL is.
 
 
 dnl 'make -f Makefile startup' will generate the configure file from 
 dnl 'make -f Makefile startup' will generate the configure file from 
-dnl configure.in correctly and can be run at any time
+dnl configure.ac correctly and can be run at any time
 
 
 AC_PREREQ(2.50)
 AC_PREREQ(2.50)
-AC_INIT(configure.in)
+AC_INIT(configure.ac)
 AC_CONFIG_AUX_DIR(buildlib)
 AC_CONFIG_AUX_DIR(buildlib)
 AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in include/apti18n.h:buildlib/apti18n.h.in)
 AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in include/apti18n.h:buildlib/apti18n.h.in)
 
 
 PACKAGE="apt"
 PACKAGE="apt"
-PACKAGE_VERSION="0.9.8~exp1~20130301"
+PACKAGE_VERSION="0.9.10"
 PACKAGE_MAIL="APT Development Team <deity@lists.debian.org>"
 PACKAGE_MAIL="APT Development Team <deity@lists.debian.org>"
 AC_DEFINE_UNQUOTED(PACKAGE,"$PACKAGE")
 AC_DEFINE_UNQUOTED(PACKAGE,"$PACKAGE")
 AC_DEFINE_UNQUOTED(PACKAGE_VERSION,"$PACKAGE_VERSION")
 AC_DEFINE_UNQUOTED(PACKAGE_VERSION,"$PACKAGE_VERSION")
@@ -180,10 +180,6 @@ AC_SUBST(DOTDIR)
 ah_NUM_PROCS
 ah_NUM_PROCS
 ah_GCC3DEP
 ah_GCC3DEP
 
 
-dnl It used to be that the user could select translations and that could get
-dnl passed to the makefiles, but now that can only work if you use special
-dnl gettext approved makefiles, so this feature is unsupported by this.
-ALL_LINGUAS="bg bs ca cs cy da de dz el es eu fi fr gl hu it ja ko ku nb nl nn pl pt_BR pt ro ru sk sl sv th tl uk vi zn_CN zh_TW"
 AM_GNU_GETTEXT(external)
 AM_GNU_GETTEXT(external)
 if test x"$USE_NLS" = "xyes"; then
 if test x"$USE_NLS" = "xyes"; then
    AC_DEFINE(USE_NLS)
    AC_DEFINE(USE_NLS)

+ 93 - 0
debian/apt.auto-removal.sh

@@ -0,0 +1,93 @@
+#!/bin/sh
+
+set -e
+
+# Author: Steve Langasek <steve.langasek@canonical.com>
+#
+# Mark as not-for-autoremoval those kernel packages that are:
+#  - the currently booted version
+#  - the kernel version we've been called for
+#  - the latest kernel version (determined using rules copied from the grub
+#    package for deciding which kernel to boot)
+#  - the second-latest kernel version, if the booted kernel version is
+#    already the latest and this script is called for that same version,
+#    to ensure a fallback remains available in the event the newly-installed
+#    kernel at this ABI fails to boot
+# In the common case, this results in exactly two kernels saved, but it can
+# result in three kernels being saved.  It's better to err on the side of
+# saving too many kernels than saving too few.
+#
+# We generate this list and save it to /etc/apt/apt.conf.d instead of marking
+# packages in the database because this runs from a postinst script, and apt
+# will overwrite the db when it exits.
+
+
+eval $(apt-config shell APT_CONF_D Dir::Etc::parts/d)
+test -n "${APT_CONF_D}" || APT_CONF_D="/etc/apt/apt.conf.d"
+config_file=${APT_CONF_D}/01autoremove-kernels
+
+eval $(apt-config shell DPKG Dir::bin::dpkg/f)
+test -n "$DPKG" || DPKG="/usr/bin/dpkg"
+
+installed_version="$1"
+running_version="$(uname -r)"
+
+
+version_test_gt ()
+{
+	local version_test_gt_sedexp="s/[._-]\(pre\|rc\|test\|git\|old\|trunk\)/~\1/g"
+	local version_a="`echo "$1" | sed -e "$version_test_gt_sedexp"`"
+	local version_b="`echo "$2" | sed -e "$version_test_gt_sedexp"`"
+	$DPKG --compare-versions "$version_a" gt "$version_b"
+	return "$?"
+}
+
+list=$(${DPKG} -l 'linux-image-[0-9]*'|awk '/^ii/ && $2 !~ /-dbg$/ { print $2 }' | sed -e's/linux-image-//')
+
+latest_version=""
+previous_version=""
+for i in $list; do
+	if version_test_gt "$i" "$latest_version"; then
+		previous_version="$latest_version"
+		latest_version="$i"
+	elif version_test_gt "$i" "$previous_version"; then
+		previous_version="$i"
+	fi
+done
+
+if [ "$latest_version" != "$installed_version" ] \
+   || [ "$latest_version" != "$running_version" ] \
+   || [ "$installed_version" != "$running_version" ]
+then
+	# We have at least two kernels that we have reason to think the
+	# user wants, so don't save the second-newest version.
+	previous_version=
+fi
+
+kernels=$(sort -u <<EOF
+$latest_version
+$installed_version
+$running_version
+$previous_version
+EOF
+)
+
+cat > "$config_file".dpkg-new <<EOF
+// File autogenerated by $0, do not edit
+APT
+{
+  NeverAutoRemove
+  {
+EOF
+for kernel in $kernels; do
+	echo "    \"^linux-image-${kernel}$\";" >> "$config_file".dpkg-new
+	echo "    \"^linux-image-extra-${kernel}$\";" >> "$config_file".dpkg-new
+	echo "    \"^linux-signed-image-${kernel}$\";" >> "$config_file".dpkg-new
+	echo "    \"^linux-backports-modules-.*-${kernel}$\";" >> "$config_file".dpkg-new
+	echo "    \"^linux-headers-${kernel}$\";" >> "$config_file".dpkg-new
+done
+cat >> "$config_file".dpkg-new <<EOF
+  };
+};
+EOF
+mv "$config_file".dpkg-new "$config_file"

+ 0 - 3
debian/apt.conf.autoremove

@@ -4,10 +4,7 @@ APT
   {
   {
 	"^firmware-linux.*";
 	"^firmware-linux.*";
 	"^linux-firmware$";
 	"^linux-firmware$";
-	"^linux-image.*";
 	"^kfreebsd-image.*";
 	"^kfreebsd-image.*";
-	"^linux-restricted-modules.*";
-	"^linux-ubuntu-modules-.*";
 	"^gnumach$";
 	"^gnumach$";
 	"^gnumach-image.*";
 	"^gnumach-image.*";
   };
   };

+ 1 - 0
debian/apt.dirs

@@ -7,6 +7,7 @@ etc/apt/apt.conf.d
 etc/apt/preferences.d
 etc/apt/preferences.d
 etc/apt/sources.list.d
 etc/apt/sources.list.d
 etc/apt/trusted.gpg.d
 etc/apt/trusted.gpg.d
+etc/kernel/postinst.d
 etc/logrotate.d
 etc/logrotate.d
 var/cache/apt/archives/partial
 var/cache/apt/archives/partial
 var/lib/apt/lists/partial
 var/lib/apt/lists/partial

+ 13 - 5
debian/apt.postinst

@@ -15,12 +15,16 @@ set -e
 
 
 case "$1" in
 case "$1" in
     configure)
     configure)
-	SECRING='/etc/apt/secring.gpg'
-	# test if secring is an empty normal file
-	if test -f $SECRING -a ! -s $SECRING; then
-		rm -f $SECRING
+	if dpkg --compare-versions "$2" lt-nl 0.9.9.5; then
+	    # we are using tmpfiles for both
+	    rm -f /etc/apt/trustdb.gpg
+	    # this removal was done unconditional since 0.8.15.3
+	    SECRING='/etc/apt/secring.gpg'
+	    # test if secring is an empty normal file
+	    if test -f $SECRING -a ! -s $SECRING; then
+	        rm -f $SECRING
+	    fi
 	fi
 	fi
-	apt-key update
 
 
         # ensure tighter permissons on the logs, see LP: #975199
         # ensure tighter permissons on the logs, see LP: #975199
         if dpkg --compare-versions "$2" lt-nl 0.9.7.7; then
         if dpkg --compare-versions "$2" lt-nl 0.9.7.7; then
@@ -28,6 +32,10 @@ case "$1" in
             chmod -f 0640 /var/log/apt/term.log* || true
             chmod -f 0640 /var/log/apt/term.log* || true
         fi
         fi
 
 
+        # create kernel autoremoval blacklist on update
+        if dpkg --compare-versions "$2" lt-nl 0.9.9.3; then
+            /etc/kernel/postinst.d/apt-auto-removal
+        fi
     ;;
     ;;
 
 
     abort-upgrade|abort-remove|abort-deconfigure)
     abort-upgrade|abort-remove|abort-deconfigure)

+ 235 - 10
debian/changelog

@@ -1,9 +1,5 @@
-apt (0.9.8~exp1) UNRELEASED; urgency=low
+apt (0.9.10~exp1) UNRELEASED; urgency=low
 
 
-  [ David Kalnischkies ]
-  * apt-pkg/contrib/strutl.cc:
-    - support \n and \r\n line endings in ReadMessages
-  
   [ Daniel Hartwig ]
   [ Daniel Hartwig ]
   * Clarify units of Acquire::http::Dl-Limit (closes: #705445)
   * Clarify units of Acquire::http::Dl-Limit (closes: #705445)
   * Show a error message if {,dist-}upgrade is used with additional
   * Show a error message if {,dist-}upgrade is used with additional
@@ -27,14 +23,216 @@ apt (0.9.8~exp1) UNRELEASED; urgency=low
   * use sha512 when available (LP: #1098752)
   * use sha512 when available (LP: #1098752)
   * [ABI-Break] lp:~mvo/apt/source-hashes:
   * [ABI-Break] lp:~mvo/apt/source-hashes:
     - use sha{512,256,1} for deb-src when available LP: #1098738
     - use sha{512,256,1} for deb-src when available LP: #1098738
- 
-  [ Marc Deslauriers ]
-  * make apt-ftparchive generate missing deb-src hashes (LP: #1078697)
 
 
  -- Michael Vogt <mvo@debian.org>  Fri, 01 Mar 2013 12:12:39 +0100
  -- Michael Vogt <mvo@debian.org>  Fri, 01 Mar 2013 12:12:39 +0100
 
 
-apt (0.9.7.9~exp3) UNRELEASED; urgency=low
+apt (0.9.10) unstable; urgency=low
+
+  The "Hello to Debconf" upload
+  
+  [ Christian Perrier ]
+  * Vietnamese translation update. Closes: #718615
+  * Japanese translation update. Closes: #719279
 
 
+  [ Michael Vogt ]
+  * work on fixing coverity scan results:
+    - fix some off-by-one errors
+    - fix some resource leaks
+    - fixes in chroot() handling
+    - fix some missing va_end()
+  * make the code -Wall clean again
+  * remove duplicated #include<list>
+  * add .travis.yml
+  * use the 'abi-complicance-checker' package and remove the buildin 
+    copy for the abi checks
+
+  [ David Kalnischkies ]
+  * ensure that FileFd::Size returns 0 in error cases
+  * add missing Turkish (tr) to po/LINGUAS
+  * correct management-typo in description found by lintian
+  * implement debian/rules build-{arch,indep} as required by policy 3.9.4
+  * reenable automatic parallel build of APT
+  * exclude config.{sub,guess} from source package
+  * update the symbol files to reflect current state
+  * unset LANGUAGE for showing [Y/n] answer hints
+  * fix some unitialized data members
+  * specific pins below 1000 cause downgrades (Closes: 543966)
+  * use pkgTagFile to parse "header" of Release files
+  * fix: --print-uris removes authentication (Closes: 719263)
+  * always use our own trustdb.gpg in apt-key
+  * use a tmpfile for trustdb.gpg in apt-key.
+    Thanks to Andreas Beckmann for the initial patch! (Closes: #687611)
+  * do not double-slash paths in apt-key (Closes: 665411)
+  * make the keyring locations in apt-key configurable
+  * let apt-key del work better with softlink and single key keyrings
+  * do not call 'apt-key update' in apt.postinst
+
+  [ Colin Watson ]
+  * prefer native arch over higher priority for providers (Closes: #718482)
+
+ -- Michael Vogt <mvo@debian.org>  Mon, 12 Aug 2013 21:45:07 +0200
+
+apt (0.9.9.4) unstable; urgency=low
+
+  [ David Kalnischkies ]
+  * pick up Translation-* even if only compressed available (Closes: 717665)
+  * request absolute URIs from proxies again (0.9.9.3 regession)
+    (Closes: 717891)
+  
+  [ Michael vogt ]
+  * fix missing changelog entry for 0.9.9.3 (git-dch issue)
+
+ -- Michael Vogt <mvo@debian.org>  Fri, 26 Jul 2013 09:58:17 +0200
+
+apt (0.9.9.3) unstable; urgency=low
+
+  [ Ben Hutchings ]
+  * debian/apt.auto-removal.sh:
+    - do not include debug symbol packages for the kernel in the 
+      blacklist (closes: #717616)
+  
+  [ Michael Vogt ]
+  * debian/apt.postinst:
+    - run /etc/kernel/postinst.d/apt-auto-removal once on upgrade
+      to ensure that the correct auto-removal list is generated
+      (closes: #717615)
+
+  [ David Kalnischkies ]
+  * skip all Description fields in apt-cache, not just first (Closes: 717254)
+  * fix 'apt-cache search' crash with missing description (Closes: 647590)
+
+  [ Raphael Geissert ]
+  * Do not send a connection: keep-alive, at all
+  
+ -- Michael Vogt <mvo@debian.org>  Thu, 25 Jul 2013 17:14:58 +0200
+
+apt (0.9.9.2) unstable; urgency=low
+
+  [ Programs translations ]
+  * Vietnamese updated by Tran Ngoc Quan. Closes: #717016
+
+  [ David Kalnischkies ]
+  * fix if-clause to generate hook-info for 'rc' packages (Closes: 717006)
+
+ -- Michael Vogt <mvo@debian.org>  Wed, 17 Jul 2013 14:56:34 +0200
+
+apt (0.9.9.1) unstable; urgency=low
+
+  [ Michael Vogt ]
+  * debian/rules:
+    - call dh_clean in clean (closes: #714980)
+  * apt-pkg/packagemanager.cc:
+    - increate APT::pkgPackageManager::MaxLoopCount to 5000
+  * cherry pick debian/apt.auto-removal.sh feature from the
+    ubuntu/master branch
+
+  [ Steve Langasek ]
+  * debian/apt.conf.autoremove: don't include linux-image*,
+    linux-restricted-modules*, and linux-ubuntu-modules* packages in the
+    list to never be autoremoved.
+  * debian/apt.auto-removal.sh, debian/rules, debian/apt.dirs: install new
+    script to /etc/kernel/postinst.d/ which ensures we only automatically
+    keep the currently-running kernel, the being-installed kernel, and the
+    newest kernel, so we don't fill /boot up with an unlimited number of
+    kernels.  LP: #923876.
+
+  [ Adam Conrad ]
+  * Fix up two things in debian/apt.auto-removal.sh:
+    - Use exact matches with $-terminated regexes, so we don't get
+      confusion between similarly-named kernel flavours.
+    - Keep linux-backports-modules in sync with installed kernels.
+
+  [ David Kalnischkies ]
+  * Version 3 for DPkg::Pre-Install-Pkgs with MultiArch info (Closes: #712116)
+  * implement arch+= and arch-= for sources.list
+  * prevent MarkInstall of unsynced Multi-Arch:same siblings
+
+ -- Michael Vogt <mvo@debian.org>  Thu, 11 Jul 2013 20:44:31 +0200
+
+apt (0.9.9) unstable; urgency=low
+
+  [ Michael Vogt ]
+  * improve debug output for the Debug::pkgProblemResolver and
+    Debug::pkgDepCache::AutoInstall
+  * improve apt-cdrom output when no CD-ROM can be auto-detected
+  * document --no-auto-detect in apt-cdrom
+
+  [ David Kalnischkies ]
+  * build the en manpages in subdirectory doc/en
+  * remove -ldl from cdrom and -lutil from apt-get linkage
+  * rewrite pkgOrderList::DepRemove to stop incorrect immediate setting
+    (Closes: 645713)
+  * prefer Essentials over Removals in ordering score
+  * fix priority sorting by prefering higher in MarkInstall
+  * try all providers in order if uninstallable in MarkInstall
+  * do unpacks before configures in SmartConfigure (Closes: #707578)
+  * fix support for multiple patterns in apt-cache search (Closes: #691453)
+  * set Fail flag in FileFd on all errors consistently
+  * don't explicitly init ExtractTar InFd with invalid fd
+  * OpenDescriptor should autoclose fd always on error (Closes: #704608)
+  * fail in CopyFile if the FileFds have error flag set
+  * ensure state-dir exists before coyping cdrom files
+  * fix file location for configure-index.gz in apt.conf(5) (Closes: #711921)
+  * handle missing "Description" in apt-cache show (Closes: #712435)
+  * try defaults if auto-detection failed in apt-cdrom (Closes: #712433)
+  * support \n and \r\n line endings in ReadMessages
+  * do not redownload unchanged InRelease files
+  * trigger NODATA error for invalid InRelease files (Closes: #712486)
+
+ -- Michael Vogt <mvo@debian.org>  Tue, 02 Jul 2013 08:58:33 +0200
+
+apt (0.9.8.2) unstable; urgency=low
+
+  [ Programs translations ]
+  * French translation : typo fix. Closes: #677272
+
+  [ Guillem Jover ]
+  * Update Vcs fields (Closes: #708562)
+  
+  [ Michael Vogt ]
+  * buildlib/apti18n.h.in:
+    - fix build failure when building without NLS (closes: #671587)
+  
+  [ Gregoire Menuel ]
+  * Fix double free (closes: #711045)
+  
+  [ Raphael Geissert ]
+  * Fix crash when the "mirror" method does not find any entry
+    (closes: #699303)
+
+  [ Johan Kiviniemi ]
+  * cmdline/apt-key:
+    - Create new keyrings with mode 0644 instead of 0600.
+    - Accept a nonexistent --keyring file with the adv subcommand as well.
+
+ -- Michael Vogt <mvo@debian.org>  Thu, 06 Jun 2013 19:15:14 +0200
+
+apt (0.9.8.1) unstable; urgency=low
+
+  [ David Kalnischkies ]
+  * apt-pkg/indexcopy.cc:
+    - non-inline RunGPGV methods to restore ABI compatibility with previous
+      versions to fix partial upgrades (Closes: #707771)
+  
+  [ Michael Vogt ]
+  * moved source to http://git.debian.org/apt/apt.git
+  * updated gbp.conf to match what bzr-buildpackage is doing
+  * remove .bzr-buildpackage/default.conf (superseeded by gbp.conf)
+
+ -- Michael Vogt <mvo@debian.org>  Thu, 16 May 2013 14:50:43 +0200
+
+apt (0.9.8) unstable; urgency=low
+
+  [ Ludovico Cavedon ]
+  * properly handle if-modfied-since with libcurl/https 
+    (closes: #705648)
+  
+  [ Andreas Beckman ]
+  * apt-pkg/algorithms.cc:
+    - Do not propagate negative scores from rdepends. Propagating the absolute
+      value of a negative score may boost obsolete packages and keep them
+      installed instead of installing their successors.  (Closes: #699759)
+  
   [ Michael Vogt ]
   [ Michael Vogt ]
   * apt-pkg/sourcelist.cc:
   * apt-pkg/sourcelist.cc:
     - fix segfault when a hostname contains a [, thanks to 
     - fix segfault when a hostname contains a [, thanks to 
@@ -64,8 +262,35 @@ apt (0.9.7.9~exp3) UNRELEASED; urgency=low
 
 
   [ Marc Deslauriers ]
   [ Marc Deslauriers ]
   * make apt-ftparchive generate missing deb-src hashes (LP: #1078697)
   * make apt-ftparchive generate missing deb-src hashes (LP: #1078697)
+  
+  [ Yaroslav Halchenko ]
+  * Fix English spelling error in a message ('A error'). Unfuzzy
+    translations. Closes: #705087
 
 
- -- Michael Vogt <mvo@debian.org>  Mon, 08 Apr 2013 08:43:21 +0200
+  [ Programs translations ]
+  * French translation completed (Christian Perrier)
+  
+  [ Manpages translations ]
+  * French translation completed (Christian Perrier)
+
+  [ Daniel Hartwig ]
+  * apt-pkg/contrib/strutl.cc:
+    - include port in shortened URIs (e.g. with apt-cache policy, progress
+      display) thanks to James McCoy (Closes: #154868, #322074)
+    - percent-encode username and password when writing URIs
+  * methods/http.cc:
+    - properly escape IP-literals (e.g. IPv6 address) when building
+      Host headers and URIs (Closes: #620344)
+  * methods/https.cc:
+    - use https_proxy environment variable if present, falling back to
+      http_proxy otherwise
+    - use authentication credentials from proxy URI
+      (Closes: #651640, LP: #1087512)
+    - environment variables do not override an explicit no proxy
+      directive ("DIRECT") in apt.conf
+    - disregard all_proxy environment variable, like other methods
+  
+ -- Michael Vogt <mvo@debian.org>  Wed, 08 May 2013 18:43:28 +0200
 
 
 apt (0.9.7.9~exp2) experimental; urgency=low
 apt (0.9.7.9~exp2) experimental; urgency=low
 
 

+ 7 - 7
debian/control

@@ -5,15 +5,15 @@ Maintainer: APT Development Team <deity@lists.debian.org>
 Uploaders: Michael Vogt <mvo@debian.org>, Otavio Salvador <otavio@debian.org>,
 Uploaders: Michael Vogt <mvo@debian.org>, Otavio Salvador <otavio@debian.org>,
  Christian Perrier <bubulle@debian.org>, Daniel Burrows <dburrows@debian.org>,
  Christian Perrier <bubulle@debian.org>, Daniel Burrows <dburrows@debian.org>,
  Julian Andres Klode <jak@debian.org>
  Julian Andres Klode <jak@debian.org>
-Standards-Version: 3.9.3
+Standards-Version: 3.9.4
 Build-Depends: dpkg-dev (>= 1.15.8), debhelper (>= 8.1.3~), libdb-dev,
 Build-Depends: dpkg-dev (>= 1.15.8), debhelper (>= 8.1.3~), libdb-dev,
- gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.0),
+ gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.4~),
  zlib1g-dev, libbz2-dev, xsltproc, docbook-xsl, docbook-xml,
  zlib1g-dev, libbz2-dev, xsltproc, docbook-xsl, docbook-xml,
  po4a (>= 0.34-2), autotools-dev, autoconf, automake
  po4a (>= 0.34-2), autotools-dev, autoconf, automake
 Build-Depends-Indep: doxygen, debiandoc-sgml
 Build-Depends-Indep: doxygen, debiandoc-sgml
 Build-Conflicts: autoconf2.13, automake1.4
 Build-Conflicts: autoconf2.13, automake1.4
-Vcs-Bzr: http://bzr.debian.org/apt/debian-sid/
-Vcs-Browser: http://bzr.debian.org/loggerhead/apt/debian-sid/
+Vcs-Git: git://anonscm.debian.org/apt/apt.git
+Vcs-Browser: http://anonscm.debian.org/gitweb/?p=apt/apt.git
 
 
 Package: apt
 Package: apt
 Architecture: any
 Architecture: any
@@ -43,7 +43,7 @@ Pre-Depends: ${misc:Pre-Depends}
 Depends: ${shlibs:Depends}, ${misc:Depends}
 Depends: ${shlibs:Depends}, ${misc:Depends}
 Breaks: apt (<< 0.9.4~)
 Breaks: apt (<< 0.9.4~)
 Section: libs
 Section: libs
-Description: package managment runtime library
+Description: package management runtime library
  This library provides the common functionality for searching and
  This library provides the common functionality for searching and
  managing packages as well as information about packages.
  managing packages as well as information about packages.
  Higher-level package managers can depend upon this library.
  Higher-level package managers can depend upon this library.
@@ -107,9 +107,9 @@ Package: apt-utils
 Architecture: any
 Architecture: any
 Depends: ${shlibs:Depends}, ${misc:Depends}
 Depends: ${shlibs:Depends}, ${misc:Depends}
 Suggests: xz-utils
 Suggests: xz-utils
-Description: package managment related utility programs
+Description: package management related utility programs
  This package contains some less used commandline utilities related
  This package contains some less used commandline utilities related
- to package managment with APT.
+ to package management with APT.
  .
  .
   * apt-extracttemplates is used by debconf to prompt for configuration
   * apt-extracttemplates is used by debconf to prompt for configuration
     questions before installation.
     questions before installation.

+ 6 - 0
debian/gbp.conf

@@ -0,0 +1,6 @@
+[DEFAULT]
+prebuild = ./prepare-release pre-export
+postbuild = ./prepare-release post-build
+export-dir = ../build-area
+debian-branch = debian/sid
+debian-tag = %(version)s

+ 1 - 5
debian/libapt-inst1.5.symbols

@@ -81,12 +81,8 @@ libapt-inst.so.1.5 libapt-inst1.5 #MINVER#
  (c++|optional)"vtable for pkgCache::VerIterator@Base" 0.8.0
  (c++|optional)"vtable for pkgCache::VerIterator@Base" 0.8.0
  (c++|optional)"vtable for pkgCache::Iterator<pkgCache::Dependency, pkgCache::DepIterator>@Base" 0.8.0
  (c++|optional)"vtable for pkgCache::Iterator<pkgCache::Dependency, pkgCache::DepIterator>@Base" 0.8.0
  (c++|optional)"vtable for pkgCache::Iterator<pkgCache::Version, pkgCache::VerIterator>@Base" 0.8.0
  (c++|optional)"vtable for pkgCache::Iterator<pkgCache::Version, pkgCache::VerIterator>@Base" 0.8.0
-### gcc-4.4 specific
-# (c++|regex|optional=std)"^char\* std::[^ ]+<.+ >::_.+@Base$" 0.8.0
-# (c++|optional=std)"std::basic_string<char, std::char_traits<char>, std::allocator<char> >& std::basic_string<char, std::char_traits<char>, std::allocator<char> >::append<unsigned char*>(unsigned char*, unsigned char*)@Base" 0.8.0
-### gcc-4.6 specific
+### gcc artefacts
  (c++|optional=std)"std::vector<APT::Configuration::Compressor, std::allocator<APT::Configuration::Compressor> >::~vector()@Base" 0.8.12
  (c++|optional=std)"std::vector<APT::Configuration::Compressor, std::allocator<APT::Configuration::Compressor> >::~vector()@Base" 0.8.12
- (c++|optional=std)"std::basic_string<char, std::char_traits<char>, std::allocator<char> >& std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace_dispatch<unsigned char*>(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, unsigned char*, unsigned char*, std::__false_type)@Base" 0.8.0
 ### try to ignore std:: template instances
 ### try to ignore std:: template instances
  (c++|regex|optional=std)"^std::basic_string<.+ >\(.+\)@Base$" 0.8.0
  (c++|regex|optional=std)"^std::basic_string<.+ >\(.+\)@Base$" 0.8.0
  (c++|regex|optional=std)"^typeinfo name for std::iterator<.*>@Base$" 0.8.0
  (c++|regex|optional=std)"^typeinfo name for std::iterator<.*>@Base$" 0.8.0

File diff suppressed because it is too large
+ 52 - 69
debian/libapt-pkg4.13.symbols


+ 27 - 19
debian/rules

@@ -66,7 +66,7 @@ LIBAPT_INST=libapt-inst$(LIBAPTINST_MAJOR)
 # do not fail as we are just experimenting with symbol files for now
 # do not fail as we are just experimenting with symbol files for now
 export DPKG_GENSYMBOLS_CHECK_LEVEL=0
 export DPKG_GENSYMBOLS_CHECK_LEVEL=0
 
 
-build: build/build-stamp
+build-binary: build/build-binary-stamp
 build-debiandoc: build/build-debiandoc-stamp
 build-debiandoc: build/build-debiandoc-stamp
 build-manpages: build/build-manpages-stamp
 build-manpages: build/build-manpages-stamp
 
 
@@ -76,15 +76,15 @@ build-manpages: build/build-manpages-stamp
 build/environment.mak: build/configure-stamp
 build/environment.mak: build/configure-stamp
 	@true
 	@true
 
 
-configure: configure.in
-build/configure-stamp: configure
+configure: configure.ac
+build/configure-stamp: configure buildlib/config.sub buildlib/config.guess
 	dh_testdir
 	dh_testdir
 	-mkdir build
 	-mkdir build
 	cp COPYING debian/copyright
 	cp COPYING debian/copyright
 	cd build && CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" CPPFLAGS="$(CPPFLAGS)" ../configure $(confflags)
 	cd build && CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" CPPFLAGS="$(CPPFLAGS)" ../configure $(confflags)
 	touch $@
 	touch $@
 
 
-build/build-stamp: build/configure-stamp
+build/build-binary-stamp: build/configure-stamp
 	# Add here commands to compile the package.
 	# Add here commands to compile the package.
 	$(MAKE) binary
 	$(MAKE) binary
 	# compat symlink for the locale split
 	# compat symlink for the locale split
@@ -110,16 +110,18 @@ build/build-manpages-stamp: build/configure-stamp
 
 
 clean:
 clean:
 	dh_testdir
 	dh_testdir
+	dh_clean
 
 
 	[ ! -f Makefile ] || $(MAKE) clean distclean
 	[ ! -f Makefile ] || $(MAKE) clean distclean
 	rm -rf build
 	rm -rf build
 	rm -f debian/$(LIBAPT_PKG).install debian/$(LIBAPT_INST).install \
 	rm -f debian/$(LIBAPT_PKG).install debian/$(LIBAPT_INST).install \
 	      debian/libapt-pkg-dev.install
 	      debian/libapt-pkg-dev.install
+	test ! -L buildlib/config.guess || rm -f buildlib/config.guess
+	test ! -L buildlib/config.sub || rm -f buildlib/config.sub
 
 
 debian/%.install: debian/%.install.in
 debian/%.install: debian/%.install.in
 	sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' $< > $@
 	sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' $< > $@
 
 
-binary-indep: apt-doc libapt-pkg-doc
 # Build architecture-independent files here.
 # Build architecture-independent files here.
 libapt-pkg-doc: build-debiandoc
 libapt-pkg-doc: build-debiandoc
 	dh_testdir -p$@
 	dh_testdir -p$@
@@ -171,9 +173,8 @@ apt-doc: build-debiandoc
 
 
 # Build architecture-dependent files here.
 # Build architecture-dependent files here.
 
 
-binary-arch: $(LIBAPT_PKG) $(LIBAPT_INST) apt libapt-pkg-dev apt-utils apt-transport-https
 apt_MANPAGES = apt apt-cache apt-cdrom apt-config apt-get apt-key apt-mark apt-secure apt apt.conf apt_preferences sources.list
 apt_MANPAGES = apt apt-cache apt-cdrom apt-config apt-get apt-key apt-mark apt-secure apt apt.conf apt_preferences sources.list
-apt: build build-manpages
+apt: build-binary build-manpages
 	dh_testdir -p$@
 	dh_testdir -p$@
 	dh_testroot -p$@
 	dh_testroot -p$@
 	dh_prep -p$@
 	dh_prep -p$@
@@ -182,6 +183,8 @@ apt: build build-manpages
 # apt install
 # apt install
 #
 #
 	cp debian/apt.conf.autoremove debian/$@/etc/apt/apt.conf.d/01autoremove
 	cp debian/apt.conf.autoremove debian/$@/etc/apt/apt.conf.d/01autoremove
+	cp debian/apt.auto-removal.sh debian/$@/etc/kernel/postinst.d/apt-auto-removal
+	chmod 755 debian/$@/etc/kernel/postinst.d/apt-auto-removal
 
 
 	# make rosetta happy and remove pot files in po/ (but leave stuff
 	# make rosetta happy and remove pot files in po/ (but leave stuff
 	# in po/domains/* untouched) and cp *.po into each domain dir
 	# in po/domains/* untouched) and cp *.po into each domain dir
@@ -203,7 +206,7 @@ apt: build build-manpages
 	dh_bugfiles -p$@
 	dh_bugfiles -p$@
 	dh_lintian -p$@
 	dh_lintian -p$@
 	dh_installexamples -p$@ $(BLD)/docs/examples/*
 	dh_installexamples -p$@ $(BLD)/docs/examples/*
-	dh_installman -p$@ $(wildcard $(patsubst %,doc/%.[158],$(apt_MANPAGES)) $(patsubst %,doc/*/%.*.[158],$(apt_MANPAGES)))
+	dh_installman -p$@ $(wildcard $(patsubst %,doc/en/%.[158],$(apt_MANPAGES)) $(patsubst %,doc/*/%.*.[158],$(apt_MANPAGES)))
 	dh_installcron -p$@
 	dh_installcron -p$@
 	dh_installdocs -p$@
 	dh_installdocs -p$@
 	dh_installchangelogs -p$@
 	dh_installchangelogs -p$@
@@ -217,7 +220,7 @@ apt: build build-manpages
 	dh_md5sums -p$@
 	dh_md5sums -p$@
 	dh_builddeb -p$@
 	dh_builddeb -p$@
 
 
-libapt-pkg-dev: build debian/libapt-pkg-dev.install
+libapt-pkg-dev: build-binary debian/libapt-pkg-dev.install
 	dh_testdir -p$@
 	dh_testdir -p$@
 	dh_testroot -p$@
 	dh_testroot -p$@
 	dh_prep -p$@
 	dh_prep -p$@
@@ -237,7 +240,7 @@ libapt-pkg-dev: build debian/libapt-pkg-dev.install
 	dh_builddeb -p$@
 	dh_builddeb -p$@
 
 
 apt-utils_MANPAGES = apt-sortpkgs apt-ftparchive apt-extracttemplates
 apt-utils_MANPAGES = apt-sortpkgs apt-ftparchive apt-extracttemplates
-apt-utils: build build-manpages
+apt-utils: build-binary build-manpages
 	dh_testdir -p$@
 	dh_testdir -p$@
 	dh_testroot -p$@
 	dh_testroot -p$@
 	dh_prep -p$@
 	dh_prep -p$@
@@ -253,7 +256,7 @@ apt-utils: build build-manpages
 	dh_installexamples -p$@
 	dh_installexamples -p$@
 
 
 	# Install the man pages..
 	# Install the man pages..
-	dh_installman -p$@ $(wildcard $(patsubst %,doc/%.[158],$(apt-utils_MANPAGES)) $(patsubst %,doc/*/%.*.[158],$(apt-utils_MANPAGES)))
+	dh_installman -p$@ $(wildcard $(patsubst %,doc/en/%.[158],$(apt-utils_MANPAGES)) $(patsubst %,doc/*/%.*.[158],$(apt-utils_MANPAGES)))
 
 
 	dh_installchangelogs -p$@
 	dh_installchangelogs -p$@
 	dh_strip -p$@
 	dh_strip -p$@
@@ -266,7 +269,7 @@ apt-utils: build build-manpages
 	dh_md5sums -p$@
 	dh_md5sums -p$@
 	dh_builddeb -p$@
 	dh_builddeb -p$@
 
 
-$(LIBAPT_PKG): build debian/$(LIBAPT_PKG).install
+$(LIBAPT_PKG): build-binary debian/$(LIBAPT_PKG).install
 	dh_testdir -p$@
 	dh_testdir -p$@
 	dh_testroot -p$@
 	dh_testroot -p$@
 	dh_prep -p$@
 	dh_prep -p$@
@@ -285,7 +288,7 @@ $(LIBAPT_PKG): build debian/$(LIBAPT_PKG).install
 	dh_md5sums -p$@
 	dh_md5sums -p$@
 	dh_builddeb -p$@
 	dh_builddeb -p$@
 
 
-$(LIBAPT_INST): build debian/$(LIBAPT_INST).install
+$(LIBAPT_INST): build-binary debian/$(LIBAPT_INST).install
 	dh_testdir -p$@
 	dh_testdir -p$@
 	dh_testroot -p$@
 	dh_testroot -p$@
 	dh_prep -p$@
 	dh_prep -p$@
@@ -304,7 +307,7 @@ $(LIBAPT_INST): build debian/$(LIBAPT_INST).install
 	dh_md5sums -p$@
 	dh_md5sums -p$@
 	dh_builddeb -p$@
 	dh_builddeb -p$@
 
 
-apt-transport-https: build libapt-pkg-dev
+apt-transport-https: build-binary libapt-pkg-dev
 	dh_testdir -p$@
 	dh_testdir -p$@
 	dh_testroot -p$@
 	dh_testroot -p$@
 	dh_prep -p$@
 	dh_prep -p$@
@@ -327,13 +330,18 @@ apt-transport-https: build libapt-pkg-dev
 	dh_md5sums -p$@
 	dh_md5sums -p$@
 	dh_builddeb -p$@
 	dh_builddeb -p$@
 
 
+buildlib/config.guess buildlib/config.sub:
+	$(MAKE) "$@"
+
 configure:
 configure:
 	$(MAKE) configure
 	$(MAKE) configure
 
 
-really-clean: clean
-	-find . -name Makefile.in -print0 | xargs --null --no-run-if-empty -- rm -f
-	find -name ChangeLog | xargs rm -f
-	rm -f l33ch-stamp
-
+# translate targets to targets required by debian-policy
+binary-arch: $(LIBAPT_PKG) $(LIBAPT_INST) apt libapt-pkg-dev apt-utils apt-transport-https
+binary-indep: apt-doc libapt-pkg-doc
 binary: binary-indep binary-arch
 binary: binary-indep binary-arch
+build-arch: build-binary
+build-indep: build-manpages build-debiandoc
+build: build-indep build-arch
+
 .PHONY: build clean binary-indep binary-arch binary
 .PHONY: build clean binary-indep binary-arch binary

File diff suppressed because it is too large
+ 522 - 146
doc/Doxyfile.in


+ 8 - 0
doc/apt-cdrom.8.xml

@@ -81,6 +81,14 @@
    &apt-cmdblurb;
    &apt-cmdblurb;
    
    
    <variablelist>
    <variablelist>
+     <varlistentry><term><option>--no-auto-detect</option></term><term><option>--cdrom</option></term>
+     <listitem><para>Do not try to auto-detect the CD-ROM path. Usually combined with the <option>--cdrom</option> option.
+      Configuration Item: <literal>Acquire::cdrom::AutoDetect</literal>.
+     </para>
+     </listitem>
+     </varlistentry>
+     
+
      <varlistentry><term><option>-d</option></term><term><option>--cdrom</option></term>
      <varlistentry><term><option>-d</option></term><term><option>--cdrom</option></term>
      <listitem><para>Mount point; specify the location to mount the CD-ROM. This
      <listitem><para>Mount point; specify the location to mount the CD-ROM. This
       mount point must be listed in <filename>/etc/fstab</filename> and
       mount point must be listed in <filename>/etc/fstab</filename> and

+ 1 - 1
doc/apt-verbatim.ent

@@ -213,7 +213,7 @@
 ">
 ">
 
 
 <!-- this will be updated by 'prepare-release' -->
 <!-- this will be updated by 'prepare-release' -->
-<!ENTITY apt-product-version "0.9.7.9~exp2">
+<!ENTITY apt-product-version "0.9.7.6ubuntu2">
 
 
 <!-- Codenames for debian releases -->
 <!-- Codenames for debian releases -->
 <!ENTITY oldstable-codename "squeeze">
 <!ENTITY oldstable-codename "squeeze">

+ 11 - 6
doc/apt.conf.5.xml

@@ -98,8 +98,7 @@ APT {
 DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
 DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
 </programlisting></informalexample>
 </programlisting></informalexample>
 
 
-   <para>In general the sample configuration file in 
-   <filename>&docdir;examples/apt.conf</filename> &configureindex;
+   <para>In general the sample configuration file &configureindex;
    is a good guide for how it should look.</para>
    is a good guide for how it should look.</para>
 
 
    <para>Case is not significant in names of configuration items, so in the
    <para>Case is not significant in names of configuration items, so in the
@@ -691,11 +690,17 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
      will abort. APT will pass the filenames of all .deb files it is going to
      will abort. APT will pass the filenames of all .deb files it is going to
      install to the commands, one per line on standard input.</para>
      install to the commands, one per line on standard input.</para>
 
 
-     <para>Version 2 of this protocol dumps more information, including the 
+     <para>Version 2 of this protocol dumps more information, including the
      protocol version, the APT configuration space and the packages, files
      protocol version, the APT configuration space and the packages, files
-     and versions being changed. Version 2 is enabled by setting 
-     <literal>DPkg::Tools::options::cmd::Version</literal> to 2. <literal>cmd</literal> is a
-     command given to <literal>Pre-Install-Pkgs</literal>.</para></listitem>
+     and versions being changed. Version 3 adds the architecture and <literal>MultiArch</literal>
+     flag to each version being dumped.</para>
+
+     <para>The version of the protocol to be used for the command
+     <literal><replaceable>cmd</replaceable></literal> can be chosen by setting
+     <literal>DPkg::Tools::options::<replaceable>cmd</replaceable>::Version</literal>
+     accordingly, the default being version 1. If APT isn't supporting the requested
+     version it will send the information in the highest version it has support for instead.
+     </para></listitem>
      </varlistentry>
      </varlistentry>
 
 
      <varlistentry><term><option>Run-Directory</option></term>
      <varlistentry><term><option>Run-Directory</option></term>

+ 38 - 0
doc/en/makefile

@@ -0,0 +1,38 @@
+# -*- make -*-
+BASE=../..
+SUBDIR=doc/en
+
+# Bring in the default rules
+include ../../buildlib/defaults.mak
+
+# Do not use XMLTO, build the manpages directly with XSLTPROC
+ifdef XSLTPROC
+# generate a list of accepted man page translations
+SOURCE = $(patsubst ../%.xml,%,$(wildcard ../*.?.xml))
+INCLUDES = ../apt.ent ../apt-verbatim.ent
+STYLESHEET=../manpage-style.xsl
+
+LOCAL := manpage-$(firstword $(SOURCE))
+$(LOCAL)-LIST := $(SOURCE)
+
+# Install generation hooks
+manpages: $($(LOCAL)-LIST) apt.8
+
+$($(LOCAL)-LIST) :: % : ../%.xml $(STYLESHEET) $(INCLUDES)
+	echo Creating man page $@
+	$(XSLTPROC) -o $@ $(STYLESHEET) $<
+
+apt.8: ../apt.8
+	cp -a ../apt.8 apt.8
+
+# Clean rule
+.PHONY: clean/$(LOCAL)
+veryclean: clean/$(LOCAL)
+clean: clean/$(LOCAL)
+clean/$(LOCAL):
+	-rm -rf $($(@F)-LIST) apt.8
+endif
+
+# Chain to the manpage rule
+SOURCE = apt.8
+include $(MANPAGE_H)

+ 1 - 1
doc/examples/configure-index

@@ -225,7 +225,7 @@ Acquire
 	Verify-Peer "false";
 	Verify-Peer "false";
 	SslCert "/etc/apt/some.pem";
 	SslCert "/etc/apt/some.pem";
 	CaPath  "/etc/ssl/certs";
 	CaPath  "/etc/ssl/certs";
-	Verify-Host" "true";
+	Verify-Host "true";
 	AllowRedirect  "true";
 	AllowRedirect  "true";
 
 
 	Timeout "120";
 	Timeout "120";

+ 19 - 53
doc/makefile

@@ -1,7 +1,6 @@
 # -*- make -*-
 # -*- make -*-
 BASE=..
 BASE=..
 SUBDIR=doc
 SUBDIR=doc
-SUBDIRS= $(dir $(wildcard */makefile))
 
 
 # Bring in the default rules
 # Bring in the default rules
 include ../buildlib/defaults.mak
 include ../buildlib/defaults.mak
@@ -13,34 +12,6 @@ include $(DEBIANDOC_H)
 
 
 doc: manpages debiandoc
 doc: manpages debiandoc
 
 
-# Do not use XMLTO, build the manpages directly with XSLTPROC
-ifdef XSLTPROC
-# generate a list of accepted man page translations
-SOURCE = $(patsubst %.xml,%,$(wildcard *.?.xml))
-INCLUDES = apt.ent apt-verbatim.ent
-STYLESHEET=manpage-style.xsl
-
-LOCAL := manpage-$(firstword $(SOURCE))
-$(LOCAL)-LIST := $(SOURCE)
-
-# Install generation hooks
-manpages: $($(LOCAL)-LIST)
-
-$($(LOCAL)-LIST) :: % : %.xml $(STYLESHEET) $(INCLUDES)
-	echo Creating man page $@
-	$(XSLTPROC) -o $@ $(STYLESHEET) $<
-
-# Clean rule
-.PHONY: veryclean/$(LOCAL)
-veryclean: veryclean/$(LOCAL)
-veryclean/$(LOCAL):
-	-rm -rf $($(@F)-LIST)
-endif
-
-# Chain to the manpage rule
-SOURCE = apt.8
-include $(MANPAGE_H)
-
 examples/sources.list: examples/sources.list.in apt-verbatim.ent
 examples/sources.list: examples/sources.list.in apt-verbatim.ent
 	sed -e 's#&stable-codename;#$(shell grep --max-count=1 '^<!ENTITY stable-codename "' apt-verbatim.ent | cut -d'"' -f 2)#g' examples/sources.list.in > examples/sources.list
 	sed -e 's#&stable-codename;#$(shell grep --max-count=1 '^<!ENTITY stable-codename "' apt-verbatim.ent | cut -d'"' -f 2)#g' examples/sources.list.in > examples/sources.list
 
 
@@ -50,42 +21,43 @@ TO = $(DOC)
 TARGET = binary
 TARGET = binary
 include $(COPY_H)
 include $(COPY_H)
 
 
-.PHONY: clean clean-subdirs veryclean veryclean-subdirs all binary doc stats
+.PHONY: clean clean/subdirs veryclean veryclean/subdirs manpages/subdirs debiandoc/subdirs all binary doc stats
 
 
-clean: clean-subdirs
-veryclean: veryclean-subdirs
+clean: clean/subdirs
+veryclean: veryclean/subdirs
+manpages: manpages/subdirs
+debiandoc: debiandoc/subdirs
 
 
-clean-subdirs:
-	for dir in $(SUBDIRS); do\
-		$(MAKE) -C $$dir clean; \
-	done
+DOCUMENTATIONPO = $(patsubst %.po,%,$(notdir $(wildcard po/*.po)))
+DOCDIRLIST = $(addsuffix /makefile,$(DOCUMENTATIONPO))
 
 
-veryclean-subdirs:
-	for dir in $(SUBDIRS); do\
-		rm -rf $$dir; \
+dirs: $(DOCDIRLIST)
+$(DOCDIRLIST) :: %/makefile : lang.makefile
+	test -d $(dir $@) || mkdir $(dir $@)
+	sed "s#@@LANG@@#$(subst /,,$(dir $@))#" $< > $@
+
+debiandoc/subdirs manpages/subdirs clean/subdirs veryclean/subdirs:
+	for dir in en $(dir $(DOCDIRLIST)); do \
+		$(MAKE) -C $$dir $(patsubst %/subdirs,%,$@); \
 	done
 	done
 
 
 stats:
 stats:
 	for i in po/*.po; do echo -n "$$i: "; msgfmt --output-file=/dev/null --statistics $$i; done
 	for i in po/*.po; do echo -n "$$i: "; msgfmt --output-file=/dev/null --statistics $$i; done
 
 
 ifdef PO4A
 ifdef PO4A
-DOCUMENTATIONPO = $(patsubst %.po,%,$(notdir $(wildcard po/*.po)))
 MANPAGEPOLIST = $(addprefix manpages-translation-,$(DOCUMENTATIONPO))
 MANPAGEPOLIST = $(addprefix manpages-translation-,$(DOCUMENTATIONPO))
 DEBIANDOCPOLIST = $(addprefix debiandoc-translation-,$(DOCUMENTATIONPO))
 DEBIANDOCPOLIST = $(addprefix debiandoc-translation-,$(DOCUMENTATIONPO))
 
 
-MANPAGEDIRLIST = $(addsuffix /makefile,$(DOCUMENTATIONPO))
+.PHONY: update-po po4a $(MANPAGEPOLIST) $(DEBIANDOCPOLIST) $(DOCDIRLIST)
 
 
-.PHONY: update-po po4a $(MANPAGEPOLIST) $(MANPAGEDIRLIST)
-
-manpages: $(MANPAGEPOLIST)
-debiandoc: $(DEBIANDOCPOLIST)
-po4a: $(MANPAGEPOLIST) $(DEBIANDOCPOLIST)
+po4a: manpages/subdirs debiandoc/subdirs
 
 
 update-po:
 update-po:
 	po4a --previous --no-backups --force --no-translations \
 	po4a --previous --no-backups --force --no-translations \
 		--package-name='$(PACKAGE)-doc' --package-version='$(PACKAGE_VERSION)' \
 		--package-name='$(PACKAGE)-doc' --package-version='$(PACKAGE_VERSION)' \
 		--msgid-bugs-address='$(PACKAGE_MAIL)' po4a.conf
 		--msgid-bugs-address='$(PACKAGE_MAIL)' po4a.conf
 
 
+manpages/subdirs: $(MANPAGEPOLIST)
 $(MANPAGEPOLIST) :: manpages-translation-% : %/makefile po4a.conf
 $(MANPAGEPOLIST) :: manpages-translation-% : %/makefile po4a.conf
 	# first line is for apt.8 (see Bug#696923)
 	# first line is for apt.8 (see Bug#696923)
 	po4a --previous --no-backups --translate-only $(dir $<)apt.ent \
 	po4a --previous --no-backups --translate-only $(dir $<)apt.ent \
@@ -100,19 +72,13 @@ $(MANPAGEPOLIST) :: manpages-translation-% : %/makefile po4a.conf
 		$(patsubst %,--translate-only $(dir $<)%,$(patsubst %.8.xml,%.$(subst /,,$(dir $<)).8.xml,$(wildcard *.8.xml))) \
 		$(patsubst %,--translate-only $(dir $<)%,$(patsubst %.8.xml,%.$(subst /,,$(dir $<)).8.xml,$(wildcard *.8.xml))) \
 		--package-name='$(PACKAGE)-doc' --package-version='$(PACKAGE_VERSION)' \
 		--package-name='$(PACKAGE)-doc' --package-version='$(PACKAGE_VERSION)' \
 		--msgid-bugs-address='$(PACKAGE_MAIL)' po4a.conf
 		--msgid-bugs-address='$(PACKAGE_MAIL)' po4a.conf
-	$(MAKE) -C $(dir $<) manpages
 
 
+debiandoc/subdirs: $(DEBIANDOCPOLIST)
 $(DEBIANDOCPOLIST) :: debiandoc-translation-% : %/makefile po4a.conf
 $(DEBIANDOCPOLIST) :: debiandoc-translation-% : %/makefile po4a.conf
 	po4a --previous --no-backups --translate-only $(dir $<)apt.ent \
 	po4a --previous --no-backups --translate-only $(dir $<)apt.ent \
 		$(patsubst %,--translate-only $(dir $<)%,$(patsubst %.sgml,%.$(subst /,,$(dir $<)).sgml,$(wildcard *.sgml))) \
 		$(patsubst %,--translate-only $(dir $<)%,$(patsubst %.sgml,%.$(subst /,,$(dir $<)).sgml,$(wildcard *.sgml))) \
 		--package-name='$(PACKAGE)-doc' --package-version='$(PACKAGE_VERSION)' \
 		--package-name='$(PACKAGE)-doc' --package-version='$(PACKAGE_VERSION)' \
 		--msgid-bugs-address='$(PACKAGE_MAIL)' po4a.conf
 		--msgid-bugs-address='$(PACKAGE_MAIL)' po4a.conf
-	$(MAKE) -C $(dir $<) debiandoc
-
-dirs: $(MANPAGEDIRLIST)
-$(MANPAGEDIRLIST) :: %/makefile : lang.makefile
-	test -d $(dir $@) || mkdir $(dir $@)
-	sed "s#@@LANG@@#$(subst /,,$(dir $@))#" $< > $@
 endif
 endif
 
 
 ifdef DOXYGEN
 ifdef DOXYGEN

File diff suppressed because it is too large
+ 147 - 138
doc/po/apt-doc.pot


File diff suppressed because it is too large
+ 179 - 180
doc/po/de.po


File diff suppressed because it is too large
+ 161 - 162
doc/po/es.po


File diff suppressed because it is too large
+ 168 - 169
doc/po/fr.po


File diff suppressed because it is too large
+ 213 - 186
doc/po/it.po


File diff suppressed because it is too large
+ 160 - 160
doc/po/ja.po


File diff suppressed because it is too large
+ 153 - 153
doc/po/pl.po


File diff suppressed because it is too large
+ 167 - 166
doc/po/pt.po


File diff suppressed because it is too large
+ 153 - 153
doc/po/pt_BR.po


+ 5 - 1
doc/sources.list.5.xml

@@ -114,10 +114,14 @@
    <literal><replaceable>setting</replaceable>=<replaceable>value</replaceable></literal>.
    <literal><replaceable>setting</replaceable>=<replaceable>value</replaceable></literal>.
    Multiple settings are separated by spaces. The following settings are supported by APT
    Multiple settings are separated by spaces. The following settings are supported by APT
    (note however that unsupported settings will be ignored silently):
    (note however that unsupported settings will be ignored silently):
-   <itemizedlist><listitem><para><literal>arch=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
+   <itemizedlist>
+   <listitem><para><literal>arch=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
    can be used to specify for which architectures information should
    can be used to specify for which architectures information should
    be downloaded. If this option is not set all architectures defined by the
    be downloaded. If this option is not set all architectures defined by the
    <literal>APT::Architectures</literal> option will be downloaded.</para></listitem>
    <literal>APT::Architectures</literal> option will be downloaded.</para></listitem>
+   <listitem><para><literal>arch+=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
+   and <literal>arch-=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
+   which can be used to add/remove architectures from the set which will be downloaded.</para></listitem>
    <listitem><para><literal>trusted=yes</literal> can be set to indicate that packages
    <listitem><para><literal>trusted=yes</literal> can be set to indicate that packages
    from this source are always authenticated even if the <filename>Release</filename> file
    from this source are always authenticated even if the <filename>Release</filename> file
    is not signed or the signature can't be checked. This disables parts of &apt-secure;
    is not signed or the signature can't be checked. This disables parts of &apt-secure;

+ 2 - 1
ftparchive/writer.cc

@@ -284,7 +284,8 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
 		  if (link(FileName.c_str(),OriginalPath) != 0)
 		  if (link(FileName.c_str(),OriginalPath) != 0)
 		  {
 		  {
 		     // Panic! Restore the symlink
 		     // Panic! Restore the symlink
-		     symlink(OldLink,OriginalPath);
+		     if (symlink(OldLink,OriginalPath) != 0)
+                        _error->Errno("symlink", "failed to restore symlink");
 		     return _error->Errno("link",_("*** Failed to link %s to %s"),
 		     return _error->Errno("link",_("*** Failed to link %s to %s"),
 					  FileName.c_str(),
 					  FileName.c_str(),
 					  OriginalPath);
 					  OriginalPath);

+ 1 - 0
methods/ftp.cc

@@ -436,6 +436,7 @@ bool FTPConn::WriteMsg(unsigned int &Ret,string &Text,const char *Fmt,...)
    char S[400];
    char S[400];
    vsnprintf(S,sizeof(S) - 4,Fmt,args);
    vsnprintf(S,sizeof(S) - 4,Fmt,args);
    strcat(S,"\r\n");
    strcat(S,"\r\n");
+   va_end(args);
  
  
    if (Debug == true)
    if (Debug == true)
       cerr << "-> '" << QuoteString(S,"") << "'" << endl;
       cerr << "-> '" << QuoteString(S,"") << "'" << endl;

+ 8 - 9
methods/gpgv.cc

@@ -55,9 +55,6 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
 					 vector<string> &NoPubKeySigners)
 					 vector<string> &NoPubKeySigners)
 {
 {
    bool const Debug = _config->FindB("Debug::Acquire::gpgv", false);
    bool const Debug = _config->FindB("Debug::Acquire::gpgv", false);
-   // setup a (empty) stringstream for formating the return value
-   std::stringstream ret;
-   ret.str("");
 
 
    if (Debug == true)
    if (Debug == true)
       std::clog << "inside VerifyGetSigners" << std::endl;
       std::clog << "inside VerifyGetSigners" << std::endl;
@@ -155,6 +152,7 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
       }
       }
    }
    }
    fclose(pipein);
    fclose(pipein);
+   free(buffer);
 
 
    int status;
    int status;
    waitpid(pid, &status, 0);
    waitpid(pid, &status, 0);
@@ -170,18 +168,19 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile,
       return "";
       return "";
    }
    }
    else if (WEXITSTATUS(status) == 1)
    else if (WEXITSTATUS(status) == 1)
-   {
       return _("At least one invalid signature was encountered.");
       return _("At least one invalid signature was encountered.");
-   }
    else if (WEXITSTATUS(status) == 111)
    else if (WEXITSTATUS(status) == 111)
+      return _("Could not execute 'gpgv' to verify signature (is gpgv installed?)");
+   else if (WEXITSTATUS(status) == 112)
    {
    {
-      ioprintf(ret, _("Could not execute 'gpgv' to verify signature (is gpgv installed?)"));
-      return ret.str();
+      // acquire system checks for "NODATA" to generate GPG errors (the others are only warnings)
+      std::string errmsg;
+      //TRANSLATORS: %s is a single techy word like 'NODATA'
+      strprintf(errmsg, _("Clearsigned file isn't valid, got '%s' (does the network require authentication?)"), "NODATA");
+      return errmsg;
    }
    }
    else
    else
-   {
       return _("Unknown error executing gpgv");
       return _("Unknown error executing gpgv");
-   }
 }
 }
 
 
 bool GPGVMethod::Fetch(FetchItem *Itm)
 bool GPGVMethod::Fetch(FetchItem *Itm)

+ 27 - 28
methods/http.cc

@@ -667,7 +667,12 @@ void HttpMethod::SendReq(FetchItem *Itm,CircleBuf &Out)
 
 
    // The HTTP server expects a hostname with a trailing :port
    // The HTTP server expects a hostname with a trailing :port
    char Buf[1000];
    char Buf[1000];
-   string ProperHost = Uri.Host;
+   string ProperHost;
+
+   if (Uri.Host.find(':') != string::npos)
+      ProperHost = '[' + Uri.Host + ']';
+   else
+      ProperHost = Uri.Host;
    if (Uri.Port != 0)
    if (Uri.Port != 0)
    {
    {
       sprintf(Buf,":%u",Uri.Port);
       sprintf(Buf,":%u",Uri.Port);
@@ -677,28 +682,27 @@ void HttpMethod::SendReq(FetchItem *Itm,CircleBuf &Out)
    // Just in case.
    // Just in case.
    if (Itm->Uri.length() >= sizeof(Buf))
    if (Itm->Uri.length() >= sizeof(Buf))
        abort();
        abort();
-       
-   /* Build the request. We include a keep-alive header only for non-proxy
-      requests. This is to tweak old http/1.0 servers that do support keep-alive
-      but not HTTP/1.1 automatic keep-alive. Doing this with a proxy server 
-      will glitch HTTP/1.0 proxies because they do not filter it out and 
-      pass it on, HTTP/1.1 says the connection should default to keep alive
-      and we expect the proxy to do this */
+
+   /* RFC 2616 §5.1.2 requires absolute URIs for requests to proxies,
+      but while its a must for all servers to accept absolute URIs,
+      it is assumed clients will sent an absolute path for non-proxies */
+   std::string requesturi;
    if (Proxy.empty() == true || Proxy.Host.empty())
    if (Proxy.empty() == true || Proxy.Host.empty())
-   {
-      // see LP bugs #1003633 and #1086997. The "+" is encoded as a workaround
-      // for a amazon S3 bug
-      sprintf(Buf,"GET %s HTTP/1.1\r\nHost: %s\r\nConnection: keep-alive\r\n",
-	      QuoteString(Uri.Path,"+~ ").c_str(),ProperHost.c_str());
-   }
+      requesturi = Uri.Path;
    else
    else
-   {
-      /* Generate a cache control header if necessary. We place a max
-       	 cache age on index files, optionally set a no-cache directive
-       	 and a no-store directive for archives. */
-      sprintf(Buf,"GET %s HTTP/1.1\r\nHost: %s\r\n",
-	      Itm->Uri.c_str(),ProperHost.c_str());
-   }
+      requesturi = Itm->Uri;
+
+   // The "+" is encoded as a workaround for a amazon S3 bug
+   // see LP bugs #1003633 and #1086997.
+   requesturi = QuoteString(requesturi, "+~ ");
+
+   /* Build the request. No keep-alive is included as it is the default
+      in 1.1, can cause problems with proxies, and we are an HTTP/1.1
+      client anyway.
+      C.f. https://tools.ietf.org/wg/httpbis/trac/ticket/158 */
+   sprintf(Buf,"GET %s HTTP/1.1\r\nHost: %s\r\n",
+	   requesturi.c_str(),ProperHost.c_str());
+
    // generate a cache control header (if needed)
    // generate a cache control header (if needed)
    if (_config->FindB("Acquire::http::No-Cache",false) == true) 
    if (_config->FindB("Acquire::http::No-Cache",false) == true) 
    {
    {
@@ -975,12 +979,7 @@ HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv)
       {
       {
 	 URI Uri = Queue->Uri;
 	 URI Uri = Queue->Uri;
 	 if (Uri.Host.empty() == false)
 	 if (Uri.Host.empty() == false)
-	 {
-	    if (Uri.Port != 0)
-	       strprintf(NextURI, "http://%s:%u", Uri.Host.c_str(), Uri.Port);
-	    else
-	       NextURI = "http://" + Uri.Host;
-	 }
+            NextURI = URI::SiteOnly(Uri);
 	 else
 	 else
 	    NextURI.clear();
 	    NextURI.clear();
 	 NextURI.append(DeQuoteString(Srv->Location));
 	 NextURI.append(DeQuoteString(Srv->Location));
@@ -1401,7 +1400,7 @@ bool HttpMethod::AutoDetectProxy()
    char buf[512];
    char buf[512];
    int InFd = Pipes[0];
    int InFd = Pipes[0];
    close(Pipes[1]);
    close(Pipes[1]);
-   int res = read(InFd, buf, sizeof(buf));
+   int res = read(InFd, buf, sizeof(buf)-1);
    ExecWait(Process, "ProxyAutoDetect", true);
    ExecWait(Process, "ProxyAutoDetect", true);
 
 
    if (res < 0)
    if (res < 0)

+ 1 - 1
methods/http.h

@@ -158,7 +158,7 @@ class HttpMethod : public pkgAcqMethod
       ERROR_UNRECOVERABLE,
       ERROR_UNRECOVERABLE,
       /** \brief The server reported a error with a error content page */
       /** \brief The server reported a error with a error content page */
       ERROR_WITH_CONTENT_PAGE,
       ERROR_WITH_CONTENT_PAGE,
-      /** \brief A error on the client side */
+      /** \brief An error on the client side */
       ERROR_NOT_FROM_SERVER,
       ERROR_NOT_FROM_SERVER,
       /** \brief A redirect or retry request */
       /** \brief A redirect or retry request */
       TRY_AGAIN_OR_REDIRECT 
       TRY_AGAIN_OR_REDIRECT 

+ 25 - 2
methods/https.cc

@@ -63,6 +63,12 @@ void HttpsMethod::SetupProxy()  					/*{{{*/
 {
 {
    URI ServerName = Queue->Uri;
    URI ServerName = Queue->Uri;
 
 
+   // Curl should never read proxy settings from the environment, as
+   // we determine which proxy to use.  Do this for consistency among
+   // methods and prevent an environment variable overriding a
+   // no-proxy ("DIRECT") setting in apt.conf.
+   curl_easy_setopt(curl, CURLOPT_PROXY, "");
+
    // Determine the proxy setting - try https first, fallback to http and use env at last
    // Determine the proxy setting - try https first, fallback to http and use env at last
    string UseProxy = _config->Find("Acquire::https::Proxy::" + ServerName.Host,
    string UseProxy = _config->Find("Acquire::https::Proxy::" + ServerName.Host,
 				   _config->Find("Acquire::http::Proxy::" + ServerName.Host).c_str());
 				   _config->Find("Acquire::http::Proxy::" + ServerName.Host).c_str());
@@ -81,7 +87,14 @@ void HttpsMethod::SetupProxy()  					/*{{{*/
       if (getenv("no_proxy") != 0 && CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
       if (getenv("no_proxy") != 0 && CheckDomainList(ServerName.Host,getenv("no_proxy")) == true)
 	 return;
 	 return;
    } else {
    } else {
-      const char* result = getenv("http_proxy");
+      const char* result = getenv("https_proxy");
+      // FIXME: Fall back to http_proxy is to remain compatible with
+      // existing setups and behaviour of apt.conf.  This should be
+      // deprecated in the future (including apt.conf).  Most other
+      // programs do not fall back to http proxy settings and neither
+      // should Apt.
+      if (result == NULL)
+         result = getenv("http_proxy");
       UseProxy = result == NULL ? "" : result;
       UseProxy = result == NULL ? "" : result;
    }
    }
 
 
@@ -92,6 +105,11 @@ void HttpsMethod::SetupProxy()  					/*{{{*/
       if (Proxy.Port != 1)
       if (Proxy.Port != 1)
 	 curl_easy_setopt(curl, CURLOPT_PROXYPORT, Proxy.Port);
 	 curl_easy_setopt(curl, CURLOPT_PROXYPORT, Proxy.Port);
       curl_easy_setopt(curl, CURLOPT_PROXY, Proxy.Host.c_str());
       curl_easy_setopt(curl, CURLOPT_PROXY, Proxy.Host.c_str());
+      if (Proxy.User.empty() == false || Proxy.Password.empty() == false)
+      {
+         curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, Proxy.User.c_str());
+         curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, Proxy.Password.c_str());
+      }
    }
    }
 }									/*}}}*/
 }									/*}}}*/
 // HttpsMethod::Fetch - Fetch an item					/*{{{*/
 // HttpsMethod::Fetch - Fetch an item					/*{{{*/
@@ -285,6 +303,11 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
    long curl_servdate;
    long curl_servdate;
    curl_easy_getinfo(curl, CURLINFO_FILETIME, &curl_servdate);
    curl_easy_getinfo(curl, CURLINFO_FILETIME, &curl_servdate);
 
 
+   // If the server returns 200 OK but the If-Modified-Since condition is not
+   // met, CURLINFO_CONDITION_UNMET will be set to 1
+   long curl_condition_unmet = 0;
+   curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &curl_condition_unmet);
+
    File->Close();
    File->Close();
 
 
    // cleanup
    // cleanup
@@ -312,7 +335,7 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
       Res.Filename = File->Name();
       Res.Filename = File->Name();
       Res.LastModified = Buf.st_mtime;
       Res.LastModified = Buf.st_mtime;
       Res.IMSHit = false;
       Res.IMSHit = false;
-      if (curl_responsecode == 304)
+      if (curl_responsecode == 304 || curl_condition_unmet)
       {
       {
 	 unlink(File->Name().c_str());
 	 unlink(File->Name().c_str());
 	 Res.IMSHit = true;
 	 Res.IMSHit = true;

+ 1 - 1
methods/makefile

@@ -39,7 +39,7 @@ include $(PROGRAM_H)
 
 
 # The cdrom method
 # The cdrom method
 PROGRAM=cdrom
 PROGRAM=cdrom
-SLIBS = -lapt-pkg -ldl $(INTLLIBS)
+SLIBS = -lapt-pkg $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
 LIB_MAKES = apt-pkg/makefile
 SOURCE = cdrom.cc
 SOURCE = cdrom.cc
 include $(PROGRAM_H)
 include $(PROGRAM_H)

+ 3 - 0
methods/mirror.cc

@@ -311,6 +311,9 @@ bool MirrorMethod::InitMirrors()
 
 
       AllMirrors.push_back(s);
       AllMirrors.push_back(s);
    }
    }
+   if (AllMirrors.empty()) {
+	return _error->Error(_("No entry found in mirror file '%s'"), MirrorFile.c_str());
+   }
    Mirror = AllMirrors[0];
    Mirror = AllMirrors[0];
    UsedMirror = Mirror;
    UsedMirror = Mirror;
    return true;
    return true;

+ 2 - 0
methods/rsh.cc

@@ -218,6 +218,8 @@ bool RSHConn::WriteMsg(std::string &Text,bool Sync,const char *Fmt,...)
    // sprintf the description
    // sprintf the description
    char S[512];
    char S[512];
    vsnprintf(S,sizeof(S) - 4,Fmt,args);
    vsnprintf(S,sizeof(S) - 4,Fmt,args);
+   va_end(args);
+
    if (Sync == true)
    if (Sync == true)
       strcat(S," 2> /dev/null || echo\n");
       strcat(S," 2> /dev/null || echo\n");
    else
    else

+ 7 - 1
po/LINGUAS

@@ -1 +1,7 @@
-ar ast bg bs ca cs cy da de dz el es eu fi fr gl hu it ja km ko ku lt mr nb ne nl nn pl pt pt_BR ro ru sk sl sv th tl uk vi zh_CN zh_TW
+## If a language isn't listed here but a po file is available the build will fail.
+## If a language is disabled deliberately, list it in a line starting with a single '#'
+
+ar ast bg bs ca cs cy da de dz el es eu fi fr gl hu it ja km ko ku lt mr nb ne nl nn pl pt pt_BR ro ru sk sl sv th tl tr uk vi zh_CN zh_TW
+
+## disabled by translator request #313283:
+# he

File diff suppressed because it is too large
+ 445 - 409
po/apt-all.pot


File diff suppressed because it is too large
+ 448 - 416
po/ar.po


+ 0 - 0
po/ast.po


Some files were not shown because too many files changed in this diff