Просмотр исходного кода

merged from lp:~donkult/apt/experimental

Michael Vogt лет назад: 14
Родитель
Сommit
7296e47e10
47 измененных файлов с 742 добавлено и 330 удалено
  1. 2 4
      apt-inst/dirstream.cc
  2. 45 49
      apt-pkg/acquire-item.cc
  3. 1 1
      apt-pkg/acquire.cc
  4. 1 1
      apt-pkg/algorithms.cc
  5. 4 2
      apt-pkg/aptconfiguration.cc
  6. 35 1
      apt-pkg/cachefile.cc
  7. 1 1
      apt-pkg/cachefilter.cc
  8. 8 0
      apt-pkg/cacheset.h
  9. 81 0
      apt-pkg/contrib/fileutl.cc
  10. 1 0
      apt-pkg/contrib/fileutl.h
  11. 3 3
      apt-pkg/contrib/strutl.cc
  12. 11 25
      apt-pkg/deb/debmetaindex.cc
  13. 15 6
      apt-pkg/deb/dpkgpm.cc
  14. 4 1
      apt-pkg/indexrecords.cc
  15. 6 8
      apt-pkg/orderlist.cc
  16. 62 35
      apt-pkg/packagemanager.cc
  17. 1 1
      apt-pkg/pkgrecords.cc
  18. 2 2
      apt-pkg/pkgsystem.cc
  19. 1 1
      apt-pkg/sourcelist.cc
  20. 1 1
      apt-pkg/srcrecords.cc
  21. 4 1
      apt-pkg/tagfile.cc
  22. 2 2
      apt-pkg/version.cc
  23. 2 1
      cmdline/acqprogress.cc
  24. 1 1
      cmdline/apt-cache.cc
  25. 3 4
      cmdline/apt-cdrom.cc
  26. 2 2
      cmdline/apt-extracttemplates.cc
  27. 43 6
      cmdline/apt-get.cc
  28. 116 20
      cmdline/apt-mark.cc
  29. 40 2
      debian/changelog
  30. 3 2
      ftparchive/cachedb.h
  31. 1 0
      ftparchive/writer.cc
  32. 4 5
      methods/ftp.cc
  33. 9 11
      methods/http.cc
  34. 5 6
      methods/http.h
  35. 2 4
      methods/https.h
  36. 1 1
      methods/mirror.cc
  37. 3 1
      methods/rsh.cc
  38. 0 42
      test/integration/Packages-bug-64141-install-dependencies-for-on-hold
  39. 50 22
      test/integration/framework
  40. 21 0
      test/integration/skip-avoid-avoiding-breaks-predepends
  41. 0 33
      test/integration/status-bug-64141-install-dependencies-for-on-hold
  42. 3 3
      test/integration/test-bug-549968-install-depends-of-not-installed
  43. 17 6
      test/integration/test-bug-612099-multiarch-conflicts
  44. 1 8
      test/integration/test-bug-624218-Translation-file-handling
  45. 15 5
      test/integration/test-bug-64141-install-dependencies-for-on-hold
  46. 29 0
      test/integration/test-releasefile-verification
  47. 80 0
      test/integration/test-suggest-installed-multiarch-silbing

+ 2 - 4
apt-inst/dirstream.cc

@@ -46,15 +46,13 @@ bool pkgDirStream::DoItem(Item &Itm,int &Fd)
 	 // fchmod deals with umask and fchown sets the ownership
 	 // fchmod deals with umask and fchown sets the ownership
 	 if (fchmod(iFd,Itm.Mode) != 0)
 	 if (fchmod(iFd,Itm.Mode) != 0)
 	 {
 	 {
-	    _error->Errno("fchmod",_("Failed to write file %s"), Itm.Name);
 	    close(iFd);
 	    close(iFd);
-	    return false;
+	    return _error->Errno("fchmod",_("Failed to write file %s"), Itm.Name);
 	 }
 	 }
 	 if (fchown(iFd,Itm.UID,Itm.GID) != 0 && errno != EPERM)
 	 if (fchown(iFd,Itm.UID,Itm.GID) != 0 && errno != EPERM)
 	 {
 	 {
-	    return _error->Errno("fchown",_("Failed to write file %s"), Itm.Name);
 	    close(iFd);
 	    close(iFd);
-	    return false;
+	    return _error->Errno("fchown",_("Failed to write file %s"), Itm.Name);
 	 }
 	 }
 	 Fd = iFd;
 	 Fd = iFd;
 	 return true;
 	 return true;

+ 45 - 49
apt-pkg/acquire-item.cc

@@ -189,14 +189,14 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
 									/*}}}*/
 									/*}}}*/
 // AcqSubIndex::AcqSubIndex - Constructor				/*{{{*/
 // AcqSubIndex::AcqSubIndex - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* Get the Index file first and see if there are languages available
- * If so, create a pkgAcqIndexTrans for the found language(s).
- */
+/* Get a sub-index file based on checksums from a 'master' file and
+   possibly query additional files */
 pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI,
 pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI,
 				 string const &URIDesc, string const &ShortDesc,
 				 string const &URIDesc, string const &ShortDesc,
 				 HashString const &ExpectedHash)
 				 HashString const &ExpectedHash)
    : Item(Owner), ExpectedHash(ExpectedHash)
    : Item(Owner), ExpectedHash(ExpectedHash)
 {
 {
+   /* XXX: Beware: Currently this class does nothing (of value) anymore ! */
    Debug = _config->FindB("Debug::pkgAcquire::SubIndex",false);
    Debug = _config->FindB("Debug::pkgAcquire::SubIndex",false);
 
 
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
@@ -236,17 +236,7 @@ void pkgAcqSubIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*
    Status = StatDone;
    Status = StatDone;
    Dequeue();
    Dequeue();
 
 
-   // No good Index is provided, so try guessing
-   std::vector<std::string> langs = APT::Configuration::getLanguages(true);
-   for (std::vector<std::string>::const_iterator l = langs.begin();
-	l != langs.end(); ++l)
-   {
-      if (*l == "none") continue;
-      string const file = "Translation-" + *l;
-      new pkgAcqIndexTrans(Owner, Desc.URI.substr(0, Desc.URI.rfind('/')+1).append(file),
-		Desc.Description.erase(Desc.Description.rfind(' ')+1).append(file),
-		file);
-   }
+   // No good Index is provided
 }
 }
 									/*}}}*/
 									/*}}}*/
 void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash,	/*{{{*/
 void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash,	/*{{{*/
@@ -305,38 +295,7 @@ bool pkgAcqSubIndex::ParseIndex(string const &IndexFile)		/*{{{*/
    indexRecords SubIndexParser;
    indexRecords SubIndexParser;
    if (FileExists(IndexFile) == false || SubIndexParser.Load(IndexFile) == false)
    if (FileExists(IndexFile) == false || SubIndexParser.Load(IndexFile) == false)
       return false;
       return false;
-
-   std::vector<std::string> lang = APT::Configuration::getLanguages(true);
-   for (std::vector<std::string>::const_iterator l = lang.begin();
-	l != lang.end(); ++l)
-   {
-      if (*l == "none")
-	 continue;
-
-      string file = "Translation-" + *l;
-      indexRecords::checkSum const *Record = SubIndexParser.Lookup(file);
-      HashString expected;
-      if (Record == NULL)
-      {
-	 // FIXME: the Index file provided by debian currently only includes bz2 records
-	 Record = SubIndexParser.Lookup(file + ".bz2");
-	 if (Record == NULL)
-	    continue;
-      }
-      else
-      {
-	 expected = Record->Hash;
-	 if (expected.empty() == true)
-	    continue;
-      }
-
-      IndexTarget target;
-      target.Description = Desc.Description.erase(Desc.Description.rfind(' ')+1).append(file);
-      target.MetaKey = file;
-      target.ShortDesc = file;
-      target.URI = Desc.URI.substr(0, Desc.URI.rfind('/')+1).append(file);
-      new pkgAcqIndexTrans(Owner, &target, expected, &SubIndexParser);
-   }
+   // so something with the downloaded index
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1385,6 +1344,18 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
       return;
       return;
    }
    }
 #endif
 #endif
+   bool transInRelease = false;
+   {
+      std::vector<std::string> const keys = MetaIndexParser->MetaKeys();
+      for (std::vector<std::string>::const_iterator k = keys.begin(); k != keys.end(); ++k)
+	 // FIXME: Feels wrong to check for hardcoded string here, but what should we do else…
+	 if (k->find("Translation-") != std::string::npos)
+	 {
+	    transInRelease = true;
+	    break;
+	 }
+   }
+
    for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
    for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
         Target != IndexTargets->end();
         Target != IndexTargets->end();
         ++Target)
         ++Target)
@@ -1422,8 +1393,15 @@ 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
-	    new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+	 else if (transInRelease == false || MetaIndexParser->Exists((*Target)->MetaKey) == true)
+	 {
+	    if (_config->FindB("Acquire::PDiffs",true) == true && transInRelease == true &&
+		MetaIndexParser->Exists(string((*Target)->MetaKey).append(".diff/Index")) == true)
+	       new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
+				   (*Target)->ShortDesc, ExpectedIndexHash);
+	    else
+	       new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+	 }
 	 continue;
 	 continue;
       }
       }
 
 
@@ -1620,6 +1598,13 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*
 {
 {
    if (AuthPass == false)
    if (AuthPass == false)
    {
    {
+      // Remove the 'old' InRelease file if we try Release.gpg now as otherwise
+      // the file will stay around and gives a false-auth impression (CVE-2012-0214)
+      string FinalFile = _config->FindDir("Dir::State::lists");
+      FinalFile.append(URItoFileName(RealURI));
+      if (FileExists(FinalFile))
+	 unlink(FinalFile.c_str());
+
       new pkgAcqMetaSig(Owner,
       new pkgAcqMetaSig(Owner,
 			MetaSigURI, MetaSigURIDesc, MetaSigShortDesc,
 			MetaSigURI, MetaSigURIDesc, MetaSigShortDesc,
 			MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
 			MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
@@ -1825,7 +1810,18 @@ bool pkgAcqArchive::QueueNext()
 	 else
 	 else
 	    PartialSize = Buf.st_size;
 	    PartialSize = Buf.st_size;
       }
       }
-      
+
+      // Disables download of archives - useful if no real installation follows,
+      // e.g. if we are just interested in proposed installation order
+      if (_config->FindB("Debug::pkgAcqArchive::NoQueue", false) == true)
+      {
+	 Complete = true;
+	 Local = true;
+	 Status = StatDone;
+	 StoreFilename = DestFile = FinalFile;
+	 return true;
+      }
+
       // Create the item
       // Create the item
       Local = false;
       Local = false;
       Desc.URI = Index->ArchiveURI(PkgFile);
       Desc.URI = Index->ArchiveURI(PkgFile);

+ 1 - 1
apt-pkg/acquire.cc

@@ -766,7 +766,7 @@ void pkgAcquire::Queue::Bump()
 // AcquireStatus::pkgAcquireStatus - Constructor			/*{{{*/
 // AcquireStatus::pkgAcquireStatus - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgAcquireStatus::pkgAcquireStatus() : Update(true), MorePulses(false)
+pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Update(true), MorePulses(false)
 {
 {
    Start();
    Start();
 }
 }

+ 1 - 1
apt-pkg/algorithms.cc

@@ -471,7 +471,7 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 // ProblemResolver::pkgProblemResolver - Constructor			/*{{{*/
 // ProblemResolver::pkgProblemResolver - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : Cache(*pCache)
+pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : d(NULL), Cache(*pCache)
 {
 {
    // Allocate memory
    // Allocate memory
    unsigned long Size = Cache.Head().PackageCount;
    unsigned long Size = Cache.Head().PackageCount;

+ 4 - 2
apt-pkg/aptconfiguration.cc

@@ -376,7 +376,7 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
 			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);
-			execv(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);
 		}
 		}
@@ -392,7 +392,9 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
 					if (arch[0] != '\0') {
 					if (arch[0] != '\0') {
 						char const* archend = arch;
 						char const* archend = arch;
 						for (; isspace(*archend) == 0 && *archend != '\0'; ++archend);
 						for (; isspace(*archend) == 0 && *archend != '\0'; ++archend);
-						archs.push_back(string(arch, (archend - arch)));
+						string a(arch, (archend - arch));
+						if (std::find(archs.begin(), archs.end(), a) == archs.end())
+							archs.push_back(a);
 					}
 					}
 					arch = strtok(NULL, " ");
 					arch = strtok(NULL, " ");
 				}
 				}

+ 35 - 1
apt-pkg/cachefile.cc

@@ -30,7 +30,7 @@
 // CacheFile::CacheFile - Constructor					/*{{{*/
 // CacheFile::CacheFile - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgCacheFile::pkgCacheFile() : Map(NULL), Cache(NULL), DCache(NULL),
+pkgCacheFile::pkgCacheFile() : d(NULL), Map(NULL), Cache(NULL), DCache(NULL),
 				SrcList(NULL), Policy(NULL)
 				SrcList(NULL), Policy(NULL)
 {
 {
 }
 }
@@ -178,6 +178,40 @@ void pkgCacheFile::RemoveCaches()
       unlink(pkgcache.c_str());
       unlink(pkgcache.c_str());
    if (srcpkgcache.empty() == false && RealFileExists(srcpkgcache) == true)
    if (srcpkgcache.empty() == false && RealFileExists(srcpkgcache) == true)
       unlink(srcpkgcache.c_str());
       unlink(srcpkgcache.c_str());
+   if (pkgcache.empty() == false)
+   {
+      std::string cachedir = flNotFile(pkgcache);
+      std::string cachefile = flNotDir(pkgcache);
+      if (cachedir.empty() != true && cachefile.empty() != true && DirectoryExists(cachedir) == true)
+      {
+	 cachefile.append(".");
+	 std::vector<std::string> caches = GetListOfFilesInDir(cachedir, false);
+	 for (std::vector<std::string>::const_iterator file = caches.begin(); file != caches.end(); ++file)
+	 {
+	    std::string nuke = flNotDir(*file);
+	    if (strncmp(cachefile.c_str(), nuke.c_str(), cachefile.length()) != 0)
+	       continue;
+	    unlink(file->c_str());
+	 }
+      }
+   }
+
+   if (srcpkgcache.empty() == true)
+      return;
+
+   std::string cachedir = flNotFile(srcpkgcache);
+   std::string cachefile = flNotDir(srcpkgcache);
+   if (cachedir.empty() == true || cachefile.empty() == true || DirectoryExists(cachedir) == false)
+      return;
+   cachefile.append(".");
+   std::vector<std::string> caches = GetListOfFilesInDir(cachedir, false);
+   for (std::vector<std::string>::const_iterator file = caches.begin(); file != caches.end(); ++file)
+   {
+      std::string nuke = flNotDir(*file);
+      if (strncmp(cachefile.c_str(), nuke.c_str(), cachefile.length()) != 0)
+	 continue;
+      unlink(file->c_str());
+   }
 }
 }
 									/*}}}*/
 									/*}}}*/
 // CacheFile::Close - close the cache files				/*{{{*/
 // CacheFile::Close - close the cache files				/*{{{*/

+ 1 - 1
apt-pkg/cachefilter.cc

@@ -18,7 +18,7 @@
 									/*}}}*/
 									/*}}}*/
 namespace APT {
 namespace APT {
 namespace CacheFilter {
 namespace CacheFilter {
-PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) {/*{{{*/
+PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) : d(NULL) {/*{{{*/
 	pattern = new regex_t;
 	pattern = new regex_t;
 	int const Res = regcomp(pattern, Pattern.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
 	int const Res = regcomp(pattern, Pattern.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
 	if (Res == 0)
 	if (Res == 0)

+ 8 - 0
apt-pkg/cacheset.h

@@ -191,6 +191,8 @@ public:									/*{{{*/
 		inline iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; }
 		inline iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; }
 		inline bool operator!=(iterator const &i) const { return _iter != i._iter; };
 		inline bool operator!=(iterator const &i) const { return _iter != i._iter; };
 		inline bool operator==(iterator const &i) const { return _iter == i._iter; };
 		inline bool operator==(iterator const &i) const { return _iter == i._iter; };
+		inline iterator& operator=(iterator const &i) { _iter = i._iter; return *this; };
+		inline iterator& operator=(typename Container::iterator const &i) { _iter = i; return *this; };
 		friend std::ostream& operator<<(std::ostream& out, iterator i) { return operator<<(out, *i); }
 		friend std::ostream& operator<<(std::ostream& out, iterator i) { return operator<<(out, *i); }
 	};
 	};
 									/*}}}*/
 									/*}}}*/
@@ -201,7 +203,9 @@ public:									/*{{{*/
 
 
 	bool empty() const { return _cont.empty(); };
 	bool empty() const { return _cont.empty(); };
 	void clear() { return _cont.clear(); };
 	void clear() { return _cont.clear(); };
+	//FIXME: on ABI break, replace the first with the second without bool
 	void erase(iterator position) { _cont.erase((typename Container::iterator)position); };
 	void erase(iterator position) { _cont.erase((typename Container::iterator)position); };
+	iterator& erase(iterator &position, bool) { return position = _cont.erase((typename Container::iterator)position); };
 	size_t erase(const pkgCache::PkgIterator x) { return _cont.erase(x); };
 	size_t erase(const pkgCache::PkgIterator x) { return _cont.erase(x); };
 	void erase(iterator first, iterator last) { _cont.erase(first, last); };
 	void erase(iterator first, iterator last) { _cont.erase(first, last); };
 	size_t size() const { return _cont.size(); };
 	size_t size() const { return _cont.size(); };
@@ -507,6 +511,8 @@ public:									/*{{{*/
 		inline iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; }
 		inline iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; }
 		inline bool operator!=(iterator const &i) const { return _iter != i._iter; };
 		inline bool operator!=(iterator const &i) const { return _iter != i._iter; };
 		inline bool operator==(iterator const &i) const { return _iter == i._iter; };
 		inline bool operator==(iterator const &i) const { return _iter == i._iter; };
+		inline iterator& operator=(iterator const &i) { _iter = i._iter; return *this; };
+		inline iterator& operator=(typename Container::iterator const &i) { _iter = i; return *this; };
 		friend std::ostream& operator<<(std::ostream& out, iterator i) { return operator<<(out, *i); }
 		friend std::ostream& operator<<(std::ostream& out, iterator i) { return operator<<(out, *i); }
 	};
 	};
 									/*}}}*/
 									/*}}}*/
@@ -516,7 +522,9 @@ public:									/*{{{*/
 	void insert(const_iterator begin, const_iterator end) { _cont.insert(begin, end); };
 	void insert(const_iterator begin, const_iterator end) { _cont.insert(begin, end); };
 	bool empty() const { return _cont.empty(); };
 	bool empty() const { return _cont.empty(); };
 	void clear() { return _cont.clear(); };
 	void clear() { return _cont.clear(); };
+	//FIXME: on ABI break, replace the first with the second without bool
 	void erase(iterator position) { _cont.erase((typename Container::iterator)position); };
 	void erase(iterator position) { _cont.erase((typename Container::iterator)position); };
+	iterator& erase(iterator &position, bool) { return position = _cont.erase((typename Container::iterator)position); };
 	size_t erase(const pkgCache::VerIterator x) { return _cont.erase(x); };
 	size_t erase(const pkgCache::VerIterator x) { return _cont.erase(x); };
 	void erase(iterator first, iterator last) { _cont.erase(first, last); };
 	void erase(iterator first, iterator last) { _cont.erase(first, last); };
 	size_t size() const { return _cont.size(); };
 	size_t size() const { return _cont.size(); };

+ 81 - 0
apt-pkg/contrib/fileutl.cc

@@ -387,6 +387,13 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
       {
       {
 	 if (RealFileExists(File.c_str()) == false)
 	 if (RealFileExists(File.c_str()) == false)
 	 {
 	 {
+	    // do not show ignoration warnings for directories
+	    if (
+#ifdef _DIRENT_HAVE_D_TYPE
+		Ent->d_type == DT_DIR ||
+#endif
+		DirectoryExists(File.c_str()) == true)
+	       continue;
 	    if (SilentIgnore.Match(Ent->d_name) == false)
 	    if (SilentIgnore.Match(Ent->d_name) == false)
 	       _error->Notice(_("Ignoring '%s' in directory '%s' as it is not a regular file"), Ent->d_name, Dir.c_str());
 	       _error->Notice(_("Ignoring '%s' in directory '%s' as it is not a regular file"), Ent->d_name, Dir.c_str());
 	    continue;
 	    continue;
@@ -454,6 +461,80 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
    }
    }
    closedir(D);
    closedir(D);
 
 
+   if (SortList == true)
+      std::sort(List.begin(),List.end());
+   return List;
+}
+std::vector<string> GetListOfFilesInDir(string const &Dir, bool SortList)
+{
+   bool const Debug = _config->FindB("Debug::GetListOfFilesInDir", false);
+   if (Debug == true)
+      std::clog << "Accept in " << Dir << " all regular files" << std::endl;
+
+   std::vector<string> List;
+
+   if (DirectoryExists(Dir.c_str()) == false)
+   {
+      _error->Error(_("List of files can't be created as '%s' is not a directory"), Dir.c_str());
+      return List;
+   }
+
+   DIR *D = opendir(Dir.c_str());
+   if (D == 0)
+   {
+      _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
+      return List;
+   }
+
+   for (struct dirent *Ent = readdir(D); Ent != 0; Ent = readdir(D)) 
+   {
+      // skip "hidden" files
+      if (Ent->d_name[0] == '.')
+	 continue;
+
+      // Make sure it is a file and not something else
+      string const File = flCombine(Dir,Ent->d_name);
+#ifdef _DIRENT_HAVE_D_TYPE
+      if (Ent->d_type != DT_REG)
+#endif
+      {
+	 if (RealFileExists(File.c_str()) == false)
+	 {
+	    if (Debug == true)
+	       std::clog << "Bad file: " << Ent->d_name << " → it is not a real file" << std::endl;
+	    continue;
+	 }
+      }
+
+      // Skip bad filenames ala run-parts
+      const char *C = Ent->d_name;
+      for (; *C != 0; ++C)
+	 if (isalpha(*C) == 0 && isdigit(*C) == 0
+	     && *C != '_' && *C != '-' && *C != '.')
+	    break;
+
+      // we don't reach the end of the name -> bad character included
+      if (*C != 0)
+      {
+	 if (Debug == true)
+	    std::clog << "Bad file: " << Ent->d_name << " → bad character »" << *C << "« in filename" << std::endl;
+	 continue;
+      }
+
+      // skip filenames which end with a period. These are never valid
+      if (*(C - 1) == '.')
+      {
+	 if (Debug == true)
+	    std::clog << "Bad file: " << Ent->d_name << " → Period as last character" << std::endl;
+	 continue;
+      }
+
+      if (Debug == true)
+	 std::clog << "Accept file: " << Ent->d_name << " in " << Dir << std::endl;
+      List.push_back(File);
+   }
+   closedir(D);
+
    if (SortList == true)
    if (SortList == true)
       std::sort(List.begin(),List.end());
       std::sort(List.begin(),List.end());
    return List;
    return List;

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

@@ -171,6 +171,7 @@ std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, std::string
 					bool const &SortList, bool const &AllowNoExt=false);
 					bool const &SortList, bool const &AllowNoExt=false);
 std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, std::vector<std::string> const &Ext,
 std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, std::vector<std::string> const &Ext,
 					bool const &SortList);
 					bool const &SortList);
+std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, bool SortList);
 std::string SafeGetCWD();
 std::string SafeGetCWD();
 void SetCloseExec(int Fd,bool Close);
 void SetCloseExec(int Fd,bool Close);
 void SetNonBlock(int Fd,bool Block);
 void SetNonBlock(int Fd,bool Block);

+ 3 - 3
apt-pkg/contrib/strutl.cc

@@ -910,17 +910,17 @@ bool StrToTime(const string &Val,time_t &Result)
 
 
    // Handle RFC 1123 time
    // Handle RFC 1123 time
    Month[0] = 0;
    Month[0] = 0;
-   if (sscanf(I," %d %3s %d %d:%d:%d GMT",&Tm.tm_mday,Month,&Tm.tm_year,
+   if (sscanf(I," %2d %3s %4d %2d:%2d:%2d GMT",&Tm.tm_mday,Month,&Tm.tm_year,
 	      &Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec) != 6)
 	      &Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec) != 6)
    {
    {
       // Handle RFC 1036 time
       // Handle RFC 1036 time
-      if (sscanf(I," %d-%3s-%d %d:%d:%d GMT",&Tm.tm_mday,Month,
+      if (sscanf(I," %2d-%3s-%3d %2d:%2d:%2d GMT",&Tm.tm_mday,Month,
 		 &Tm.tm_year,&Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec) == 6)
 		 &Tm.tm_year,&Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec) == 6)
 	 Tm.tm_year += 1900;
 	 Tm.tm_year += 1900;
       else
       else
       {
       {
 	 // asctime format
 	 // asctime format
-	 if (sscanf(I," %3s %d %d:%d:%d %d",Month,&Tm.tm_mday,
+	 if (sscanf(I," %3s %2d %2d:%2d:%2d %4d",Month,&Tm.tm_mday,
 		    &Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec,&Tm.tm_year) != 6)
 		    &Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec,&Tm.tm_year) != 6)
 	 {
 	 {
 	    // 'ftp' time
 	    // 'ftp' time

+ 11 - 25
apt-pkg/deb/debmetaindex.cc

@@ -128,7 +128,7 @@ string debReleaseIndex::TranslationIndexURISuffix(const char *Type, const string
 {
 {
    string Res ="";
    string Res ="";
    if (Dist[Dist.size() - 1] != '/')
    if (Dist[Dist.size() - 1] != '/')
-      Res += Section + "/i18n/";
+      Res += Section + "/i18n/Translation-";
    return Res + Type;
    return Res + Type;
 }
 }
 
 
@@ -210,31 +210,17 @@ vector <struct IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const {
 	if (lang.empty() == true)
 	if (lang.empty() == true)
 		return IndexTargets;
 		return IndexTargets;
 
 
-	// get the Translations:
-	// - if its a dists-style repository get the i18n/Index first
-	// - if its flat try to acquire files by guessing
-	if (Dist[Dist.size() - 1] == '/') {
-		for (std::set<std::string>::const_iterator s = sections.begin();
-		     s != sections.end(); ++s) {
-			for (std::vector<std::string>::const_iterator l = lang.begin();
-			     l != lang.end(); ++l) {
-				IndexTarget * Target = new OptionalIndexTarget();
-				Target->ShortDesc = "Translation-" + *l;
-				Target->MetaKey = TranslationIndexURISuffix(l->c_str(), *s);
-				Target->URI = TranslationIndexURI(l->c_str(), *s);
-				Target->Description = Info (Target->ShortDesc.c_str(), *s);
-				IndexTargets->push_back(Target);
-			}
-		}
-	} else {
-		for (std::set<std::string>::const_iterator s = sections.begin();
-		     s != sections.end(); ++s) {
-			IndexTarget * Target = new OptionalSubIndexTarget();
-			Target->ShortDesc = "TranslationIndex";
-			Target->MetaKey = TranslationIndexURISuffix("Index", *s);
-			Target->URI = TranslationIndexURI("Index", *s);
+	// get the Translation-* files, later we will skip download of non-existent if we have an index
+	for (std::set<std::string>::const_iterator s = sections.begin();
+	     s != sections.end(); ++s) {
+		for (std::vector<std::string>::const_iterator l = lang.begin();
+		     l != lang.end(); ++l) {
+			IndexTarget * Target = new OptionalIndexTarget();
+			Target->ShortDesc = "Translation-" + *l;
+			Target->MetaKey = TranslationIndexURISuffix(l->c_str(), *s);
+			Target->URI = TranslationIndexURI(l->c_str(), *s);
 			Target->Description = Info (Target->ShortDesc.c_str(), *s);
 			Target->Description = Info (Target->ShortDesc.c_str(), *s);
-			IndexTargets->push_back (Target);
+			IndexTargets->push_back(Target);
 		}
 		}
 	}
 	}
 
 

+ 15 - 6
apt-pkg/deb/dpkgpm.cc

@@ -51,8 +51,10 @@ using namespace std;
 class pkgDPkgPMPrivate 
 class pkgDPkgPMPrivate 
 {
 {
 public:
 public:
-   pkgDPkgPMPrivate() : dpkgbuf_pos(0), term_out(NULL), history_out(NULL)
+   pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
+			term_out(NULL), history_out(NULL)
    {
    {
+      dpkgbuf[0] = '\0';
    }
    }
    bool stdin_is_dev_null;
    bool stdin_is_dev_null;
    // the buffer we use for the dpkg status-fd reading
    // the buffer we use for the dpkg status-fd reading
@@ -860,6 +862,8 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds,
 */
 */
 bool pkgDPkgPM::Go(int OutStatusFd)
 bool pkgDPkgPM::Go(int OutStatusFd)
 {
 {
+   pkgPackageManager::SigINTStop = false;
+
    // Generate the base argument list for dpkg
    // Generate the base argument list for dpkg
    std::vector<const char *> Args;
    std::vector<const char *> Args;
    unsigned long StartSize = 0;
    unsigned long StartSize = 0;
@@ -905,7 +909,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       dup2(nullfd, STDIN_FILENO);
       dup2(nullfd, STDIN_FILENO);
       dup2(nullfd, STDOUT_FILENO);
       dup2(nullfd, STDOUT_FILENO);
       dup2(nullfd, STDERR_FILENO);
       dup2(nullfd, STDERR_FILENO);
-      execv(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);
    }
    }
@@ -1429,9 +1433,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 }
 }
 
 
 void SigINT(int sig) {
 void SigINT(int sig) {
-   if (_config->FindB("APT::Immediate-Configure-All",false)) 
-      pkgPackageManager::SigINTStop = true;
-} 
+   pkgPackageManager::SigINTStop = true;
+}
 									/*}}}*/
 									/*}}}*/
 // pkgDpkgPM::Reset - Dump the contents of the command list		/*{{{*/
 // pkgDpkgPM::Reset - Dump the contents of the command list		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
@@ -1446,6 +1449,12 @@ void pkgDPkgPM::Reset()
 /* */
 /* */
 void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) 
 void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) 
 {
 {
+   // If apport doesn't exist or isn't installed do nothing
+   // This e.g. prevents messages in 'universes' without apport
+   pkgCache::PkgIterator apportPkg = Cache.FindPkg("apport");
+   if (apportPkg.end() == true || apportPkg->CurrentVer == 0)
+      return;
+
    string pkgname, reportfile, srcpkgname, pkgver, arch;
    string pkgname, reportfile, srcpkgname, pkgver, arch;
    string::size_type pos;
    string::size_type pos;
    FILE *report;
    FILE *report;
@@ -1533,7 +1542,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
 	 if(strstr(strbuf,"Package:") == strbuf)
 	 if(strstr(strbuf,"Package:") == strbuf)
 	 {
 	 {
 	    char pkgname[255], version[255];
 	    char pkgname[255], version[255];
-	    if(sscanf(strbuf, "Package: %s %s", pkgname, version) == 2)
+	    if(sscanf(strbuf, "Package: %254s %254s", pkgname, version) == 2)
 	       if(strcmp(pkgver.c_str(), version) == 0)
 	       if(strcmp(pkgver.c_str(), version) == 0)
 	       {
 	       {
 		  fclose(report);
 		  fclose(report);

+ 4 - 1
apt-pkg/indexrecords.cc

@@ -44,7 +44,10 @@ time_t indexRecords::GetValidUntil() const
 
 
 const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
 const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
 {
 {
-   return Entries[MetaKey];
+   std::map<std::string, indexRecords::checkSum* >::const_iterator sum = Entries.find(MetaKey);
+   if (sum == Entries.end())
+      return NULL;
+   return sum->second;
 }
 }
 
 
 bool indexRecords::Exists(string const &MetaKey) const
 bool indexRecords::Exists(string const &MetaKey) const

+ 6 - 8
apt-pkg/orderlist.cc

@@ -82,16 +82,14 @@ pkgOrderList *pkgOrderList::Me = 0;
 // OrderList::pkgOrderList - Constructor				/*{{{*/
 // OrderList::pkgOrderList - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgOrderList::pkgOrderList(pkgDepCache *pCache) : Cache(*pCache)
+pkgOrderList::pkgOrderList(pkgDepCache *pCache) : Cache(*pCache),
+						  Primary(NULL), Secondary(NULL),
+						  RevDepends(NULL), Remove(NULL),
+						  AfterEnd(NULL), FileList(NULL),
+						  LoopCount(-1), Depth(0)
 {
 {
-   FileList = 0;
-   Primary = 0;
-   Secondary = 0;
-   RevDepends = 0;
-   Remove = 0;
-   LoopCount = -1;
    Debug = _config->FindB("Debug::pkgOrderList",false);
    Debug = _config->FindB("Debug::pkgOrderList",false);
-   
+
    /* Construct the arrays, egcs 1.0.1 bug requires the package count
    /* Construct the arrays, egcs 1.0.1 bug requires the package count
       hack */
       hack */
    unsigned long Size = Cache.Head().PackageCount;
    unsigned long Size = Cache.Head().PackageCount;

+ 62 - 35
apt-pkg/packagemanager.cc

@@ -36,11 +36,13 @@ bool pkgPackageManager::SigINTStop = false;
 // PM::PackageManager - Constructor					/*{{{*/
 // PM::PackageManager - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgPackageManager::pkgPackageManager(pkgDepCache *pCache) : Cache(*pCache)
+pkgPackageManager::pkgPackageManager(pkgDepCache *pCache) : Cache(*pCache),
+							    List(NULL), Res(Incomplete)
 {
 {
    FileNames = new string[Cache.Head().PackageCount];
    FileNames = new string[Cache.Head().PackageCount];
-   List = 0;
    Debug = _config->FindB("Debug::pkgPackageManager",false);
    Debug = _config->FindB("Debug::pkgPackageManager",false);
+   NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
+   ImmConfigureAll = _config->FindB("APT::Immediate-Configure-All",false);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // PM::PackageManager - Destructor					/*{{{*/
 // PM::PackageManager - Destructor					/*{{{*/
@@ -169,10 +171,7 @@ bool pkgPackageManager::CreateOrderList()
    
    
    delete List;
    delete List;
    List = new pkgOrderList(&Cache);
    List = new pkgOrderList(&Cache);
-   
-   NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
-   ImmConfigureAll = _config->FindB("APT::Immediate-Configure-All",false);
-   
+
    if (Debug && ImmConfigureAll) 
    if (Debug && ImmConfigureAll) 
       clog << "CreateOrderList(): Adding Immediate flag for all packages because of APT::Immediate-Configure-All" << endl;
       clog << "CreateOrderList(): Adding Immediate flag for all packages because of APT::Immediate-Configure-All" << endl;
    
    
@@ -690,7 +689,6 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
 	 {
 	 {
 	    VerIterator Ver(Cache,*I);
 	    VerIterator Ver(Cache,*I);
 	    PkgIterator BrokenPkg = Ver.ParentPkg();
 	    PkgIterator BrokenPkg = Ver.ParentPkg();
-	    VerIterator InstallVer(Cache,Cache[BrokenPkg].InstallVer);
 	    if (BrokenPkg.CurrentVer() != Ver)
 	    if (BrokenPkg.CurrentVer() != Ver)
 	    {
 	    {
 	       if (Debug)
 	       if (Debug)
@@ -699,35 +697,64 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
 	    }
 	    }
 
 
 	    // Check if it needs to be unpacked
 	    // Check if it needs to be unpacked
-	    if (List->IsFlag(BrokenPkg,pkgOrderList::InList) && Cache[BrokenPkg].Delete() == false && 
+	    if (List->IsFlag(BrokenPkg,pkgOrderList::InList) && Cache[BrokenPkg].Delete() == false &&
 	        List->IsNow(BrokenPkg)) {
 	        List->IsNow(BrokenPkg)) {
-	      if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop) {
-	        // This dependancy has already been dealt with by another SmartUnPack on Pkg
-	        break;
-	      } else if (List->IsFlag(Pkg,pkgOrderList::Loop)) {
-	        /* Found a break, so unpack the package, but dont remove loop as already set.
-	           This means that there is another SmartUnPack call for this 
-	           package and it will remove the loop flag. */
-	        if (Debug) 
-	          cout << OutputInDepth(Depth) << "  Unpacking " << BrokenPkg.Name() << " to avoid break" << endl;
-	            
-	        SmartUnPack(BrokenPkg, false, Depth + 1);
-	      } else {
-                List->Flag(Pkg,pkgOrderList::Loop);
-	        // Found a break, so unpack the package
-	        if (Debug) 
-	          cout << OutputInDepth(Depth) << "  Unpacking " << BrokenPkg.Name() << " to avoid break" << endl;
-	         
-	        SmartUnPack(BrokenPkg, false, Depth + 1);
-	        List->RmFlag(Pkg,pkgOrderList::Loop);
-	      }
-	    }
-	    
-	    // Check if a package needs to be removed
-	    if (Cache[BrokenPkg].Delete() == true && !List->IsFlag(BrokenPkg,pkgOrderList::Configured)) {
-	      if (Debug) 
-	         cout << OutputInDepth(Depth) << "  Removing " << BrokenPkg.Name() << " to avoid break" << endl;
-	      SmartRemove(BrokenPkg);
+	       if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop) {
+		  // This dependancy has already been dealt with by another SmartUnPack on Pkg
+		  break;
+	       } else {
+		  // Found a break, so see if we can unpack the package to avoid it
+		  // but do not set loop if another SmartUnPack already deals with it
+		  VerIterator InstallVer(Cache,Cache[BrokenPkg].InstallVer);
+		  bool circle = false;
+		  for (pkgCache::DepIterator D = InstallVer.DependsList(); D.end() == false; ++D)
+		  {
+		     if (D->Type != pkgCache::Dep::PreDepends)
+			continue;
+		     SPtrArray<Version *> VL = D.AllTargets();
+		     for (Version **I = VL; *I != 0; ++I)
+		     {
+			VerIterator V(Cache,*I);
+			PkgIterator P = V.ParentPkg();
+			// we are checking for installation as an easy 'protection' against or-groups and (unchosen) providers
+			if (P->CurrentVer == 0 || P != Pkg || (P.CurrentVer() != V && Cache[P].InstallVer != V))
+			   continue;
+			circle = true;
+			break;
+		     }
+		     if (circle == true)
+			break;
+		  }
+		  if (circle == true)
+		  {
+		     if (Debug)
+		        cout << OutputInDepth(Depth) << "  Avoiding " << End << " avoided as " << BrokenPkg.FullName() << " has a pre-depends on " << Pkg.FullName() << std::endl;
+		     continue;
+		  }
+		  else
+		  {
+		     if (Debug)
+		     {
+			cout << OutputInDepth(Depth) << "  Unpacking " << BrokenPkg.FullName() << " to avoid " << End;
+			if (PkgLoop == true)
+			   cout << " (Looping)";
+			cout << std::endl;
+		     }
+		     if (PkgLoop == false)
+			List->Flag(Pkg,pkgOrderList::Loop);
+		     SmartUnPack(BrokenPkg, false, Depth + 1);
+		     if (PkgLoop == false)
+			List->RmFlag(Pkg,pkgOrderList::Loop);
+		  }
+	       }
+	    } else {
+	       // Check if a package needs to be removed
+	       if (Cache[BrokenPkg].Delete() == true && !List->IsFlag(BrokenPkg,pkgOrderList::Configured))
+	       {
+		  if (Debug)
+		     cout << OutputInDepth(Depth) << "  Removing " << BrokenPkg.Name() << " to avoid " << End << endl;
+		  SmartRemove(BrokenPkg);
+	       }
 	    }
 	    }
 	 }
 	 }
       }
       }

+ 1 - 1
apt-pkg/pkgrecords.cc

@@ -22,7 +22,7 @@
 // Records::pkgRecords - Constructor					/*{{{*/
 // Records::pkgRecords - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This will create the necessary structures to access the status files */
 /* This will create the necessary structures to access the status files */
-pkgRecords::pkgRecords(pkgCache &Cache) : Cache(Cache), 
+pkgRecords::pkgRecords(pkgCache &Cache) : d(NULL), Cache(Cache),
   Files(Cache.HeaderP->PackageFileCount)
   Files(Cache.HeaderP->PackageFileCount)
 {
 {
    for (pkgCache::PkgFileIterator I = Cache.FileBegin();
    for (pkgCache::PkgFileIterator I = Cache.FileBegin();

+ 2 - 2
apt-pkg/pkgsystem.cc

@@ -26,11 +26,11 @@ unsigned long pkgSystem::GlobalListLen = 0;
 // System::pkgSystem - Constructor					/*{{{*/
 // System::pkgSystem - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Add it to the global list.. */
 /* Add it to the global list.. */
-pkgSystem::pkgSystem()
+pkgSystem::pkgSystem() : Label(NULL), VS(NULL)
 {
 {
    assert(GlobalListLen < sizeof(SysList)/sizeof(*SysList));
    assert(GlobalListLen < sizeof(SysList)/sizeof(*SysList));
    SysList[GlobalListLen] = this;
    SysList[GlobalListLen] = this;
-   GlobalListLen++;
+   ++GlobalListLen;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // System::GetSystem - Get the named system				/*{{{*/
 // System::GetSystem - Get the named system				/*{{{*/

+ 1 - 1
apt-pkg/sourcelist.cc

@@ -33,7 +33,7 @@ unsigned long pkgSourceList::Type::GlobalListLen = 0;
 // Type::Type - Constructor						/*{{{*/
 // Type::Type - Constructor						/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Link this to the global list of items*/
 /* Link this to the global list of items*/
-pkgSourceList::Type::Type()
+pkgSourceList::Type::Type() : Name(NULL), Label(NULL)
 {
 {
    ItmList[GlobalListLen] = this;
    ItmList[GlobalListLen] = this;
    GlobalListLen++;
    GlobalListLen++;

+ 1 - 1
apt-pkg/srcrecords.cc

@@ -25,7 +25,7 @@
 // SrcRecords::pkgSrcRecords - Constructor				/*{{{*/
 // SrcRecords::pkgSrcRecords - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Open all the source index files */
 /* Open all the source index files */
-pkgSrcRecords::pkgSrcRecords(pkgSourceList &List) : Files(0), Current(0)
+pkgSrcRecords::pkgSrcRecords(pkgSourceList &List) : d(NULL), Files(0), Current(0)
 {
 {
    for (pkgSourceList::const_iterator I = List.begin(); I != List.end(); ++I)
    for (pkgSourceList::const_iterator I = List.begin(); I != List.end(); ++I)
    {
    {

+ 4 - 1
apt-pkg/tagfile.cc

@@ -30,7 +30,10 @@ using std::string;
 class pkgTagFilePrivate
 class pkgTagFilePrivate
 {
 {
 public:
 public:
-   pkgTagFilePrivate(FileFd *pFd, unsigned long long Size) : Fd(*pFd), Size(Size)
+   pkgTagFilePrivate(FileFd *pFd, unsigned long long Size) : Fd(*pFd), Buffer(NULL),
+							     Start(NULL), End(NULL),
+							     Done(false), iOffset(0),
+							     Size(Size)
    {
    {
    }
    }
    FileFd &Fd;
    FileFd &Fd;

+ 2 - 2
apt-pkg/version.cc

@@ -23,10 +23,10 @@ unsigned long pkgVersioningSystem::GlobalListLen = 0;
 // pkgVS::pkgVersioningSystem - Constructor				/*{{{*/
 // pkgVS::pkgVersioningSystem - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Link to the global list of versioning systems supported */
 /* Link to the global list of versioning systems supported */
-pkgVersioningSystem::pkgVersioningSystem()
+pkgVersioningSystem::pkgVersioningSystem() : Label(NULL)
 {
 {
    VSList[GlobalListLen] = this;
    VSList[GlobalListLen] = this;
-   GlobalListLen++;
+   ++GlobalListLen;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // pkgVS::GetVS - Find a VS by name					/*{{{*/
 // pkgVS::GetVS - Find a VS by name					/*{{{*/

+ 2 - 1
cmdline/acqprogress.cc

@@ -31,8 +31,9 @@ using namespace std;
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet) :
 AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet) :
-    ScreenWidth(ScreenWidth), Quiet(Quiet)
+    ScreenWidth(ScreenWidth), ID(0), Quiet(Quiet)
 {
 {
+   BlankLine[0] = 0;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // AcqTextStatus::Start - Downloading has started			/*{{{*/
 // AcqTextStatus::Start - Downloading has started			/*{{{*/

+ 1 - 1
cmdline/apt-cache.cc

@@ -1739,7 +1739,7 @@ int main(int argc,const char *argv[])					/*{{{*/
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {'o',"option",0,CommandLine::ArbItem},
       {0,"installed","APT::Cache::Installed",0},
       {0,"installed","APT::Cache::Installed",0},
-      {0,"pre-depends","APT::Cache::ShowPreDepends",0},
+      {0,"pre-depends","APT::Cache::ShowPre-Depends",0},
       {0,"depends","APT::Cache::ShowDepends",0},
       {0,"depends","APT::Cache::ShowDepends",0},
       {0,"recommends","APT::Cache::ShowRecommends",0},
       {0,"recommends","APT::Cache::ShowRecommends",0},
       {0,"suggests","APT::Cache::ShowSuggests",0},
       {0,"suggests","APT::Cache::ShowSuggests",0},

+ 3 - 4
cmdline/apt-cdrom.cc

@@ -150,10 +150,9 @@ 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 {
    } else {
@@ -178,10 +177,10 @@ bool DoIdent(CommandLine &)
    bool res = true;
    bool res = true;
 
 
    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 {
    } else {

+ 2 - 2
cmdline/apt-extracttemplates.cc

@@ -53,8 +53,8 @@ pkgCache *DebFile::Cache = 0;
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 DebFile::DebFile(const char *debfile)
 DebFile::DebFile(const char *debfile)
-	: File(debfile, FileFd::ReadOnly), Control(0), DepOp(0), 
-          PreDepOp(0), Config(0), Template(0), Which(None)
+	: File(debfile, FileFd::ReadOnly), Size(0), Control(NULL), ControlLen(0),
+	  DepOp(0), PreDepOp(0), Config(0), Template(0), Which(None)
 {
 {
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 43 - 6
cmdline/apt-get.cc

@@ -713,11 +713,32 @@ public:
 	}
 	}
 
 
 	virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
 	virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
-		APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
-		if (verset.empty() == false)
-			return *(verset.begin());
-		if (ShowError == true)
-			ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
+		if (Pkg->ProvidesList != 0)
+		{
+			APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
+			if (verset.empty() == false)
+				return *(verset.begin());
+			if (ShowError == true)
+				ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
+		}
+		else
+		{
+			pkgCache::GrpIterator Grp = Pkg.Group();
+			pkgCache::PkgIterator P = Grp.PackageList();
+			for (; P.end() != true; P = Grp.NextPkg(P))
+			{
+				if (P == Pkg)
+					continue;
+				if (P->CurrentVer != 0) {
+					// TRANSLATORS: Note, this is not an interactive question
+					ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
+						 Pkg.FullName(true).c_str(), P.FullName(true).c_str());
+					break;
+				}
+			}
+			if (P.end() == true)
+				ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+		}
 		return pkgCache::VerIterator(Cache, 0);
 		return pkgCache::VerIterator(Cache, 0);
 	}
 	}
 
 
@@ -904,7 +925,23 @@ struct TryToRemove {
       if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
       if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
 	  (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
 	  (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
       {
       {
-	 ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+	 pkgCache::GrpIterator Grp = Pkg.Group();
+	 pkgCache::PkgIterator P = Grp.PackageList();
+	 for (; P.end() != true; P = Grp.NextPkg(P))
+	 {
+	    if (P == Pkg)
+	       continue;
+	    if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled))
+	    {
+	       // TRANSLATORS: Note, this is not an interactive question
+	       ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
+			Pkg.FullName(true).c_str(), P.FullName(true).c_str());
+	       break;
+	    }
+	 }
+	 if (P.end() == true)
+	    ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+
 	 // MarkInstall refuses to install packages on hold
 	 // MarkInstall refuses to install packages on hold
 	 Pkg->SelectedState = pkgCache::State::Hold;
 	 Pkg->SelectedState = pkgCache::State::Hold;
       }
       }

+ 116 - 20
cmdline/apt-mark.cc

@@ -14,9 +14,15 @@
 #include <apt-pkg/init.h>
 #include <apt-pkg/init.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/fileutl.h>
 
 
 #include <algorithm>
 #include <algorithm>
+#include <errno.h>
 #include <unistd.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
 
 
 #include <apti18n.h>
 #include <apti18n.h>
 									/*}}}*/
 									/*}}}*/
@@ -158,13 +164,63 @@ bool DoHold(CommandLine &CmdL)
    if (unlikely(Cache == NULL))
    if (unlikely(Cache == NULL))
       return false;
       return false;
 
 
+   // Generate the base argument list for dpkg
+   std::vector<const char *> Args;
+   string Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
+   {
+      string const dpkgChrootDir = _config->FindDir("DPkg::Chroot-Directory", "/");
+      size_t dpkgChrootLen = dpkgChrootDir.length();
+      if (dpkgChrootDir != "/" && Tmp.find(dpkgChrootDir) == 0)
+      {
+	 if (dpkgChrootDir[dpkgChrootLen - 1] == '/')
+	    --dpkgChrootLen;
+	 Tmp = Tmp.substr(dpkgChrootLen);
+      }
+   }
+   Args.push_back(Tmp.c_str());
+
+   // Stick in any custom dpkg options
+   Configuration::Item const *Opts = _config->Tree("DPkg::Options");
+   if (Opts != 0)
+   {
+      Opts = Opts->Child;
+      for (; Opts != 0; Opts = Opts->Next)
+      {
+	 if (Opts->Value.empty() == true)
+	    continue;
+	 Args.push_back(Opts->Value.c_str());
+      }
+   }
+
+   size_t const BaseArgs = Args.size();
+   // we need to detect if we can qualify packages with the architecture or not
+   Args.push_back("--assert-multi-arch");
+   Args.push_back(NULL);
+
+
+   pid_t dpkgAssertMultiArch = ExecFork();
+   if (dpkgAssertMultiArch == 0)
+   {
+      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
+      int const nullfd = open("/dev/null", O_RDONLY);
+      dup2(nullfd, STDIN_FILENO);
+      dup2(nullfd, STDOUT_FILENO);
+      dup2(nullfd, STDERR_FILENO);
+      execvp(Args[0], (char**) &Args[0]);
+      _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!");
+      _exit(2);
+   }
+
    APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1);
    APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1);
    if (pkgset.empty() == true)
    if (pkgset.empty() == true)
       return _error->Error(_("No packages found"));
       return _error->Error(_("No packages found"));
 
 
    bool const MarkHold = strcasecmp(CmdL.FileList[0],"hold") == 0;
    bool const MarkHold = strcasecmp(CmdL.FileList[0],"hold") == 0;
 
 
-   for (APT::PackageList::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+   for (APT::PackageList::iterator Pkg = pkgset.begin(); Pkg != pkgset.end();)
    {
    {
       if ((Pkg->SelectedState == pkgCache::State::Hold) == MarkHold)
       if ((Pkg->SelectedState == pkgCache::State::Hold) == MarkHold)
       {
       {
@@ -172,9 +228,25 @@ bool DoHold(CommandLine &CmdL)
 	    ioprintf(c1out,_("%s was already set on hold.\n"), Pkg.FullName(true).c_str());
 	    ioprintf(c1out,_("%s was already set on hold.\n"), Pkg.FullName(true).c_str());
 	 else
 	 else
 	    ioprintf(c1out,_("%s was already not hold.\n"), Pkg.FullName(true).c_str());
 	    ioprintf(c1out,_("%s was already not hold.\n"), Pkg.FullName(true).c_str());
-	 pkgset.erase(Pkg);
-	 continue;
+	 Pkg = pkgset.erase(Pkg, true);
+      }
+      else
+	 ++Pkg;
+   }
+
+   bool dpkgMultiArch = false;
+   if (dpkgAssertMultiArch > 0)
+   {
+      int Status = 0;
+      while (waitpid(dpkgAssertMultiArch, &Status, 0) != dpkgAssertMultiArch)
+      {
+	 if (errno == EINTR)
+	    continue;
+	 _error->WarningE("dpkgGo", _("Waited for %s but it wasn't there"), "dpkg --assert-multi-arch");
+	 break;
       }
       }
+      if (WIFEXITED(Status) == true && WEXITSTATUS(Status) == 0)
+	 dpkgMultiArch = true;
    }
    }
 
 
    if (pkgset.empty() == true)
    if (pkgset.empty() == true)
@@ -192,36 +264,60 @@ bool DoHold(CommandLine &CmdL)
       return true;
       return true;
    }
    }
 
 
-   string dpkgcall = _config->Find("Dir::Bin::dpkg", "dpkg");
-   std::vector<string> const dpkgoptions = _config->FindVector("DPkg::options");
-   for (std::vector<string>::const_iterator o = dpkgoptions.begin();
-	o != dpkgoptions.end(); ++o)
-      dpkgcall.append(" ").append(*o);
-   dpkgcall.append(" --set-selections");
-   FILE *dpkg = popen(dpkgcall.c_str(), "w");
-   if (dpkg == NULL)
-      return _error->Errno("DoHold", "fdopen on dpkg stdin failed");
+   Args.erase(Args.begin() + BaseArgs, Args.end());
+   Args.push_back("--set-selections");
+   Args.push_back(NULL);
+
+   int external[2] = {-1, -1};
+   if (pipe(external) != 0)
+      return _error->WarningE("DoHold", "Can't create IPC pipe for dpkg --set-selections");
 
 
+   pid_t dpkgSelection = ExecFork();
+   if (dpkgSelection == 0)
+   {
+      close(external[1]);
+      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 --set-selections", chrootDir.c_str());
+      int const nullfd = open("/dev/null", O_RDONLY);
+      dup2(external[0], STDIN_FILENO);
+      dup2(nullfd, STDOUT_FILENO);
+      dup2(nullfd, STDERR_FILENO);
+      execvp(Args[0], (char**) &Args[0]);
+      _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!");
+      _exit(2);
+   }
+
+   FILE* dpkg = fdopen(external[1], "w");
    for (APT::PackageList::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
    for (APT::PackageList::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
    {
    {
       if (MarkHold == true)
       if (MarkHold == true)
       {
       {
-	 fprintf(dpkg, "%s hold\n", Pkg.FullName(true).c_str());
+	 fprintf(dpkg, "%s hold\n", Pkg.FullName(!dpkgMultiArch).c_str());
 	 ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str());
 	 ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str());
       }
       }
       else
       else
       {
       {
-	 fprintf(dpkg, "%s install\n", Pkg.FullName(true).c_str());
+	 fprintf(dpkg, "%s install\n", Pkg.FullName(!dpkgMultiArch).c_str());
 	 ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str());
 	 ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str());
       }
       }
    }
    }
+   fclose(dpkg);
 
 
-   int const status = pclose(dpkg);
-   if (status == -1)
-      return _error->Errno("DoHold", "dpkg execution failed in the end");
-   if (WIFEXITED(status) == false || WEXITSTATUS(status) != 0)
-      return _error->Error(_("Executing dpkg failed. Are you root?"));
-   return true;
+   if (dpkgSelection > 0)
+   {
+      int Status = 0;
+      while (waitpid(dpkgSelection, &Status, 0) != dpkgSelection)
+      {
+	 if (errno == EINTR)
+	    continue;
+	 _error->WarningE("dpkgGo", _("Waited for %s but it wasn't there"), "dpkg --set-selection");
+	 break;
+      }
+      if (WIFEXITED(Status) == true && WEXITSTATUS(Status) == 0)
+	 return true;
+   }
+   return _error->Error(_("Executing dpkg failed. Are you root?"));
 }
 }
 									/*}}}*/
 									/*}}}*/
 /* ShowHold - show packages set on hold in dpkg status			{{{*/
 /* ShowHold - show packages set on hold in dpkg status			{{{*/

+ 40 - 2
debian/changelog

@@ -1,9 +1,20 @@
 apt (0.8.16~exp13) UNRELEASED; urgency=low
 apt (0.8.16~exp13) UNRELEASED; urgency=low
 
 
   [ David Kalnischkies ]
   [ David Kalnischkies ]
+  * apt-pkg/acquire-item.cc:
+    - remove 'old' InRelease file if we can't get a new one before
+      proceeding with Release.gpg to avoid the false impression of a still
+      trusted repository by a (still present) old InRelease file.
+      Thanks to Simon Ruderich for reporting this issue! (CVE-2012-0214)
+    - add Debug::pkgAcqArchive::NoQueue to disable package downloading
   * apt-pkg/deb/dpkgpm.cc:
   * apt-pkg/deb/dpkgpm.cc:
     - chroot if needed before dpkg --assert-multi-arch
     - chroot if needed before dpkg --assert-multi-arch
     - ensure that dpkg binary doesn't have the chroot-directory prefixed
     - ensure that dpkg binary doesn't have the chroot-directory prefixed
+    - call dpkg --assert-multi-arch with execvp instead of execv
+    - save the universe by not printing messages about apport if a package
+      with this name is not installed (Closes: #619646)
+    - handle a SIGINT in all modes as a break after the currently running
+      dpkg transaction instead of ignoring it completely
   * apt-pkg/depcache.cc:
   * apt-pkg/depcache.cc:
     - if a M-A:same package is marked for reinstall, mark all it's installed
     - if a M-A:same package is marked for reinstall, mark all it's installed
       silbings for reinstallation as well (LP: #859188)
       silbings for reinstallation as well (LP: #859188)
@@ -13,8 +24,35 @@ apt (0.8.16~exp13) UNRELEASED; urgency=low
     - if a file without an extension is requested send an 'Accept: text/*'
     - if a file without an extension is requested send an 'Accept: text/*'
       header to avoid that the server chooses unsupported compressed files
       header to avoid that the server chooses unsupported compressed files
       in a content-negotation attempt (Closes: #657560)
       in a content-negotation attempt (Closes: #657560)
+    - remove the arbitrary MAXLEN limit for response lines (Closes: #658346)
   * apt-pkg/aptconfiguration.cc:
   * apt-pkg/aptconfiguration.cc:
     - chroot if needed before calling dpkg --print-foreign-architectures
     - chroot if needed before calling dpkg --print-foreign-architectures
+    - ensure that architectures are not added multiple times
+  * cmdline/apt-mark.cc:
+    - detect if dpkg has multiarch support before calling --set-selections
+    - correctly ignore already (un)hold packages
+  * apt-pkg/cachefile.cc:
+    - clean up lost atomic cachefiles with 'clean' (Closes: #650513)
+  * apt-pkg/indexrecords.cc:
+    - do not create empty Entries as a sideeffect of Lookup()
+  * apt-pkg/acquire-item.cc:
+    - drop support for i18n/Index file (introduced in 0.8.11) and use
+      the Release file instead to get the Translations (Closes: #649314)
+    - use pdiff for Translation-* files if available (Closes: #657902)
+  * ftparchive/writer.cc:
+    - add 'Translation-*' to the default patterns
+  * cmdline/apt-get.cc:
+    - if a package can't be removed as it is not installed, suggest to
+      the user an (installed) multiarch silbing with 'Did you mean?'
+    - improve 'error' message for packages which are only referenced
+      e.g. in a Depends line and are now requested for removal
+  * cmdline/apt-cache.cc:
+    - correct --pre-depends option by using dash consistently (LP: #940837)
+  * apt-pkg/packagemanager.cc:
+    - do not try to a void a breaks if the broken package pre-depends
+      on the breaker, but let dpkg auto-deconfigure it
+  * apt-pkg/contrib/fileutl.cc:
+    - do not warn about the ignoring of directories (Closes: #662762)
 
 
   [ Steve Langasek ]
   [ Steve Langasek ]
   * cmdline/apt-get.cc:
   * cmdline/apt-get.cc:
@@ -29,7 +67,7 @@ apt (0.8.16~exp13) UNRELEASED; urgency=low
       become so big now that it can overflow (Closes: #657732, LP: #917173)
       become so big now that it can overflow (Closes: #657732, LP: #917173)
   * Fix IndexCopy::CopyPackages and TranslationsCopy::CopyTranslations to
   * Fix IndexCopy::CopyPackages and TranslationsCopy::CopyTranslations to
     handle compressed files again (LP: #924182, closes: #658096)
     handle compressed files again (LP: #924182, closes: #658096)
-  
+
   [ Michael Vogt ]
   [ Michael Vogt ]
   * apt-pkg/deb/dpkgpm.cc:
   * apt-pkg/deb/dpkgpm.cc:
     - fix crash when a package is in removed but residual config state
     - fix crash when a package is in removed but residual config state
@@ -50,7 +88,7 @@ apt (0.8.16~exp13) UNRELEASED; urgency=low
     - Not automatically installed during dist-upgrade
     - Not automatically installed during dist-upgrade
     - No higher score for installation ordering
     - No higher score for installation ordering
 
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Mon, 30 Jan 2012 19:17:09 +0100
+ -- David Kalnischkies <kalnischkies@gmail.com>  Tue, 06 Mar 2012 17:57:22 +0100
 
 
 apt (0.8.16~exp12) experimental; urgency=low
 apt (0.8.16~exp12) experimental; urgency=low
 
 

+ 3 - 2
ftparchive/cachedb.h

@@ -126,7 +126,8 @@ class CacheDB
          Misses += S.Misses; 
          Misses += S.Misses; 
          DeLinkBytes += S.DeLinkBytes;
          DeLinkBytes += S.DeLinkBytes;
       };
       };
-      Stats() : Bytes(0), MD5Bytes(0), SHA1Bytes(0), SHA256Bytes(0), Packages(0), Misses(0), DeLinkBytes(0) {};
+      Stats() : Bytes(0), MD5Bytes(0), SHA1Bytes(0), SHA256Bytes(0),
+		SHA512Bytes(0),Packages(0), Misses(0), DeLinkBytes(0) {};
    } Stats;
    } Stats;
    
    
    bool ReadyDB(std::string const &DB);
    bool ReadyDB(std::string const &DB);
@@ -142,7 +143,7 @@ class CacheDB
    
    
    bool Clean();
    bool Clean();
    
    
-   CacheDB(std::string const &DB) : Dbp(0), Fd(NULL), DebFile(0) {ReadyDB(DB);};
+   CacheDB(std::string const &DB) : Dbp(0), Fd(NULL), DebFile(0) {TmpKey[0]='\0'; ReadyDB(DB);};
    ~CacheDB() {ReadyDB(std::string()); delete DebFile;};
    ~CacheDB() {ReadyDB(std::string()); delete DebFile;};
 };
 };
     
     

+ 1 - 0
ftparchive/writer.cc

@@ -941,6 +941,7 @@ ReleaseWriter::ReleaseWriter(string const &DB)
       AddPattern("Packages.bz2");
       AddPattern("Packages.bz2");
       AddPattern("Packages.lzma");
       AddPattern("Packages.lzma");
       AddPattern("Packages.xz");
       AddPattern("Packages.xz");
+      AddPattern("Translation-*");
       AddPattern("Sources");
       AddPattern("Sources");
       AddPattern("Sources.gz");
       AddPattern("Sources.gz");
       AddPattern("Sources.bz2");
       AddPattern("Sources.bz2");

+ 4 - 5
methods/ftp.cc

@@ -77,6 +77,7 @@ FTPConn::FTPConn(URI Srv) : Len(0), ServerFd(-1), DataFd(-1),
 {
 {
    Debug = _config->FindB("Debug::Acquire::Ftp",false);
    Debug = _config->FindB("Debug::Acquire::Ftp",false);
    PasvAddr = 0;
    PasvAddr = 0;
+   Buffer[0] = '\0';
 }
 }
 									/*}}}*/
 									/*}}}*/
 // FTPConn::~FTPConn - Destructor					/*{{{*/
 // FTPConn::~FTPConn - Destructor					/*{{{*/
@@ -621,8 +622,7 @@ bool FTPConn::ExtGoPasv()
    }
    }
    
    
    // Get a new passive address.
    // Get a new passive address.
-   int Res;
-   if ((Res = getaddrinfo(IP.c_str(),PStr,&Hints,&PasvAddr)) != 0)
+   if (getaddrinfo(IP.c_str(),PStr,&Hints,&PasvAddr) != 0)
       return true;
       return true;
    
    
    return true;
    return true;
@@ -720,14 +720,13 @@ bool FTPConn::CreateDataFd()
    DataListenFd = -1;
    DataListenFd = -1;
 
 
    // Get the information for a listening socket.
    // Get the information for a listening socket.
-   struct addrinfo *BindAddr = 0;
+   struct addrinfo *BindAddr = NULL;
    struct addrinfo Hints;
    struct addrinfo Hints;
    memset(&Hints,0,sizeof(Hints));
    memset(&Hints,0,sizeof(Hints));
    Hints.ai_socktype = SOCK_STREAM;
    Hints.ai_socktype = SOCK_STREAM;
    Hints.ai_flags |= AI_PASSIVE;
    Hints.ai_flags |= AI_PASSIVE;
    Hints.ai_family = ((struct sockaddr *)&ServerAddr)->sa_family;
    Hints.ai_family = ((struct sockaddr *)&ServerAddr)->sa_family;
-   int Res;
-   if ((Res = getaddrinfo(0,"0",&Hints,&BindAddr)) != 0)
+   if (getaddrinfo(0,"0",&Hints,&BindAddr) != 0 || BindAddr == NULL)
       return _error->Error(_("getaddrinfo was unable to get a listening socket"));
       return _error->Error(_("getaddrinfo was unable to get a listening socket"));
    
    
    // Construct the socket
    // Construct the socket

+ 9 - 11
methods/http.cc

@@ -42,6 +42,7 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <errno.h>
 #include <errno.h>
 #include <string.h>
 #include <string.h>
+#include <climits>
 #include <iostream>
 #include <iostream>
 #include <map>
 #include <map>
 
 
@@ -534,10 +535,6 @@ bool ServerState::HeaderLine(string Line)
    if (Line.empty() == true)
    if (Line.empty() == true)
       return true;
       return true;
 
 
-   // The http server might be trying to do something evil.
-   if (Line.length() >= MAXLEN)
-      return _error->Error(_("Got a single header line over %u chars"),MAXLEN);
-
    string::size_type Pos = Line.find(' ');
    string::size_type Pos = Line.find(' ');
    if (Pos == string::npos || Pos+1 > Line.length())
    if (Pos == string::npos || Pos+1 > Line.length())
    {
    {
@@ -561,7 +558,7 @@ bool ServerState::HeaderLine(string Line)
       // Evil servers return no version
       // Evil servers return no version
       if (Line[4] == '/')
       if (Line[4] == '/')
       {
       {
-	 int const elements = sscanf(Line.c_str(),"HTTP/%u.%u %u%[^\n]",&Major,&Minor,&Result,Code);
+	 int const elements = sscanf(Line.c_str(),"HTTP/%3u.%3u %3u%359[^\n]",&Major,&Minor,&Result,Code);
 	 if (elements == 3)
 	 if (elements == 3)
 	 {
 	 {
 	    Code[0] = '\0';
 	    Code[0] = '\0';
@@ -575,7 +572,7 @@ bool ServerState::HeaderLine(string Line)
       {
       {
 	 Major = 0;
 	 Major = 0;
 	 Minor = 9;
 	 Minor = 9;
-	 if (sscanf(Line.c_str(),"HTTP %u%[^\n]",&Result,Code) != 2)
+	 if (sscanf(Line.c_str(),"HTTP %3u%359[^\n]",&Result,Code) != 2)
 	    return _error->Error(_("The HTTP server sent an invalid reply header"));
 	    return _error->Error(_("The HTTP server sent an invalid reply header"));
       }
       }
 
 
@@ -585,7 +582,7 @@ bool ServerState::HeaderLine(string Line)
 	 Persistent = false;
 	 Persistent = false;
       else
       else
       {
       {
-	 if (Major == 1 && Minor <= 0)
+	 if (Major == 1 && Minor == 0)
 	    Persistent = false;
 	    Persistent = false;
 	 else
 	 else
 	    Persistent = true;
 	    Persistent = true;
@@ -603,9 +600,10 @@ bool ServerState::HeaderLine(string Line)
       // The length is already set from the Content-Range header
       // The length is already set from the Content-Range header
       if (StartPos != 0)
       if (StartPos != 0)
 	 return true;
 	 return true;
-      
-      if (sscanf(Val.c_str(),"%llu",&Size) != 1)
-	 return _error->Error(_("The HTTP server sent an invalid Content-Length header"));
+
+      Size = strtoull(Val.c_str(), NULL, 10);
+      if (Size == ULLONG_MAX)
+	 return _error->Errno("HeaderLine", _("The HTTP server sent an invalid Content-Length header"));
       return true;
       return true;
    }
    }
 
 
@@ -1329,7 +1327,7 @@ int HttpMethod::Loop()
                after the same URI is seen twice in a queue item. */
                after the same URI is seen twice in a queue item. */
             StringVector &R = Redirected[Queue->DestFile];
             StringVector &R = Redirected[Queue->DestFile];
             bool StopRedirects = false;
             bool StopRedirects = false;
-            if (R.size() == 0)
+            if (R.empty() == true)
                R.push_back(Queue->Uri);
                R.push_back(Queue->Uri);
             else if (R[0] == "STOP" || R.size() > 10)
             else if (R[0] == "STOP" || R.size() > 10)
                StopRedirects = true;
                StopRedirects = true;

+ 5 - 6
methods/http.h

@@ -11,8 +11,6 @@
 #ifndef APT_HTTP_H
 #ifndef APT_HTTP_H
 #define APT_HTTP_H
 #define APT_HTTP_H
 
 
-#define MAXLEN 360
-
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 
 
 #include <string>
 #include <string>
@@ -92,7 +90,7 @@ struct ServerState
    unsigned int Major;
    unsigned int Major;
    unsigned int Minor;
    unsigned int Minor;
    unsigned int Result;
    unsigned int Result;
-   char Code[MAXLEN];
+   char Code[360];
    
    
    // These are some statistics from the last parsed header lines
    // These are some statistics from the last parsed header lines
    unsigned long long Size;
    unsigned long long Size;
@@ -117,9 +115,10 @@ struct ServerState
   
   
    bool HeaderLine(std::string Line);
    bool HeaderLine(std::string Line);
    bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;};
    bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;};
-   void Reset() {Major = 0; Minor = 0; Result = 0; Size = 0; StartPos = 0;
-                 Encoding = Closes; time(&Date); ServerFd = -1; 
-                 Pipeline = true;};
+   void Reset() {Major = 0; Minor = 0; Result = 0; Code[0] = '\0'; Size = 0;
+		 StartPos = 0; Encoding = Closes; time(&Date); HaveContent = false;
+		 State = Header; Persistent = false; ServerFd = -1;
+		 Pipeline = true;};
 
 
    /** \brief Result of the header acquire */
    /** \brief Result of the header acquire */
    enum RunHeadersResult {
    enum RunHeadersResult {

+ 2 - 4
methods/https.h

@@ -8,10 +8,8 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 
 
-#ifndef APT_HTTP_H
-#define APT_HTTP_H
-
-#define MAXLEN 360
+#ifndef APT_HTTPS_H
+#define APT_HTTPS_H
 
 
 #include <iostream>
 #include <iostream>
 #include <curl/curl.h>
 #include <curl/curl.h>

+ 1 - 1
methods/mirror.cc

@@ -147,7 +147,7 @@ bool MirrorMethod::DownloadMirrorFile(string mirror_uri_str)
    // append all architectures
    // append all architectures
    std::vector<std::string> vec = APT::Configuration::getArchitectures();
    std::vector<std::string> vec = APT::Configuration::getArchitectures();
    for (std::vector<std::string>::const_iterator I = vec.begin();
    for (std::vector<std::string>::const_iterator I = vec.begin();
-        I != vec.end(); I++)
+        I != vec.end(); ++I)
       if (I == vec.begin())
       if (I == vec.begin())
          fetch += "?arch" + (*I);
          fetch += "?arch" + (*I);
       else
       else

+ 3 - 1
methods/rsh.cc

@@ -42,7 +42,9 @@ int RSHMethod::FailFd = -1;
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 RSHConn::RSHConn(URI Srv) : Len(0), WriteFd(-1), ReadFd(-1),
 RSHConn::RSHConn(URI Srv) : Len(0), WriteFd(-1), ReadFd(-1),
-                            ServerName(Srv), Process(-1) {}
+                            ServerName(Srv), Process(-1) {
+   Buffer[0] = '\0';
+}
 									/*}}}*/
 									/*}}}*/
 // RSHConn::RSHConn - Destructor					/*{{{*/
 // RSHConn::RSHConn - Destructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------

+ 0 - 42
test/integration/Packages-bug-64141-install-dependencies-for-on-hold

@@ -1,42 +0,0 @@
-Package: apt
-Priority: important
-Section: admin
-Installed-Size: 6048
-Maintainer: APT Development Team <deity@lists.debian.org>
-Architecture: i386
-Version: 0.8.10
-Provides: libapt-pkg4.10
-Depends: libc6 (>= 2.10), libdb4.8
-Breaks: oldcrap
-Filename: pool/main/a/apt/apt_0.8.10_i386.deb
-Size: 2160758
-MD5sum: 5aa2234f7b91056d430669cddf6e6e50
-Description: Advanced front-end for dpkg
-
-Package: libc6
-Priority: required
-Section: libs
-Installed-Size: 9356
-Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org>
-Architecture: i386
-Source: eglibc
-Version: 2.11.2-7
-Provides: glibc-2.11-1
-Filename: pool/main/e/eglibc/libc6_2.11.2-7_i386.deb
-Size: 3880868
-MD5sum: c48fd2854fc62125824267d086600793
-Description: Embedded GNU C Library: Shared libraries
-
-Package: libdb4.8
-Priority: standard
-Section: libs
-Installed-Size: 1488
-Maintainer: Clint Adams <clint@gnu.org>
-Architecture: i386
-Source: db4.8
-Version: 4.8.30-3
-Depends: libc6 (>= 2.3.6-6~)
-Filename: pool/main/d/db4.8/libdb4.8_4.8.30-3_i386.deb
-Size: 681988
-MD5sum: 0d58c15898a95436d2ec480aa22693ff
-Description: Berkeley v4.8 Database Libraries [runtime]

+ 50 - 22
test/integration/framework

@@ -29,7 +29,8 @@ msgtest() {
 	while [ -n "$1" ]; do
 	while [ -n "$1" ]; do
 		echo -n "${CINFO}$1${CCMD} " >&2;
 		echo -n "${CINFO}$1${CCMD} " >&2;
 		echo -n "$(echo "$2" | sed -e 's/^aptc/apt-c/' -e 's/^aptg/apt-g/' -e 's/^aptf/apt-f/')${CINFO} " >&2;
 		echo -n "$(echo "$2" | sed -e 's/^aptc/apt-c/' -e 's/^aptg/apt-g/' -e 's/^aptf/apt-f/')${CINFO} " >&2;
-		shift 2
+		shift
+		if [ -n "$1" ]; then shift; else break; fi
 	done
 	done
 	echo -n "…${CNORMAL} " >&2;
 	echo -n "…${CNORMAL} " >&2;
 }
 }
@@ -114,9 +115,9 @@ addtrap() {
 
 
 setupenvironment() {
 setupenvironment() {
 	TMPWORKINGDIRECTORY=$(mktemp -d)
 	TMPWORKINGDIRECTORY=$(mktemp -d)
-	local TESTDIR=$(readlink -f $(dirname $0))
+	TESTDIRECTORY=$(readlink -f $(dirname $0))
 	msgninfo "Preparing environment for ${CCMD}$(basename $0)${CINFO} in ${TMPWORKINGDIRECTORY}… "
 	msgninfo "Preparing environment for ${CCMD}$(basename $0)${CINFO} in ${TMPWORKINGDIRECTORY}… "
-	BUILDDIRECTORY="${TESTDIR}/../../build/bin"
+	BUILDDIRECTORY="${TESTDIRECTORY}/../../build/bin"
 	test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first"
 	test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first"
 	local OLDWORKINGDIRECTORY=$(pwd)
 	local OLDWORKINGDIRECTORY=$(pwd)
 	addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY;"
 	addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY;"
@@ -126,25 +127,19 @@ setupenvironment() {
 	mkdir -p etc/apt/apt.conf.d etc/apt/sources.list.d etc/apt/trusted.gpg.d etc/apt/preferences.d
 	mkdir -p etc/apt/apt.conf.d etc/apt/sources.list.d etc/apt/trusted.gpg.d etc/apt/preferences.d
 	mkdir -p var/cache var/lib var/log
 	mkdir -p var/cache var/lib var/log
 	mkdir -p var/lib/dpkg/info var/lib/dpkg/updates var/lib/dpkg/triggers
 	mkdir -p var/lib/dpkg/info var/lib/dpkg/updates var/lib/dpkg/triggers
-	local STATUSFILE=$(echo "$(basename $0)" | sed -e 's/^test-/status-/' -e 's/^skip-/status-/')
-	if [ -f "${TESTDIR}/${STATUSFILE}" ]; then
-		cp "${TESTDIR}/${STATUSFILE}" var/lib/dpkg/status
-	else
-		touch var/lib/dpkg/status
-	fi
 	touch var/lib/dpkg/available
 	touch var/lib/dpkg/available
 	mkdir -p usr/lib/apt
 	mkdir -p usr/lib/apt
 	ln -s ${BUILDDIRECTORY}/methods usr/lib/apt/methods
 	ln -s ${BUILDDIRECTORY}/methods usr/lib/apt/methods
 	cd ..
 	cd ..
 	local PACKAGESFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Packages-/' -e 's/^skip-/Packages-/')
 	local PACKAGESFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Packages-/' -e 's/^skip-/Packages-/')
-	if [ -f "${TESTDIR}/${PACKAGESFILE}" ]; then
-		cp "${TESTDIR}/${PACKAGESFILE}" aptarchive/Packages
+	if [ -f "${TESTDIRECTORY}/${PACKAGESFILE}" ]; then
+		cp "${TESTDIRECTORY}/${PACKAGESFILE}" aptarchive/Packages
 	fi
 	fi
 	local SOURCESSFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Sources-/' -e 's/^skip-/Sources-/')
 	local SOURCESSFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Sources-/' -e 's/^skip-/Sources-/')
-	if [ -f "${TESTDIR}/${SOURCESSFILE}" ]; then
-		cp "${TESTDIR}/${SOURCESSFILE}" aptarchive/Sources
+	if [ -f "${TESTDIRECTORY}/${SOURCESSFILE}" ]; then
+		cp "${TESTDIRECTORY}/${SOURCESSFILE}" aptarchive/Sources
 	fi
 	fi
-	cp $(find $TESTDIR -name '*.pub' -o -name '*.sec') keys/
+	cp $(find $TESTDIRECTORY -name '*.pub' -o -name '*.sec') keys/
 	ln -s ${TMPWORKINGDIRECTORY}/keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
 	ln -s ${TMPWORKINGDIRECTORY}/keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
 	echo "Dir \"${TMPWORKINGDIRECTORY}/rootdir\";" > aptconfig.conf
 	echo "Dir \"${TMPWORKINGDIRECTORY}/rootdir\";" > aptconfig.conf
 	echo "Dir::state::status \"${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg/status\";" >> aptconfig.conf
 	echo "Dir::state::status \"${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg/status\";" >> aptconfig.conf
@@ -156,7 +151,9 @@ setupenvironment() {
 	echo "DPKG::options:: \"--root=${TMPWORKINGDIRECTORY}/rootdir\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--root=${TMPWORKINGDIRECTORY}/rootdir\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--force-not-root\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--force-not-root\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--force-bad-path\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--force-bad-path\";" >> aptconfig.conf
-	echo "DPKG::options:: \"--force-architecture\";" >> aptconfig.conf # Added to test multiarch before dpkg is ready for it…
+	if ! $(which dpkg) --assert-multi-arch; then
+		echo "DPKG::options:: \"--force-architecture\";" >> aptconfig.conf # Added to test multiarch before dpkg is ready for it…
+	fi
 	echo "DPKG::options:: \"--log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log\";" >> aptconfig.conf
 	echo 'quiet::NoUpdate "true";' >> aptconfig.conf
 	echo 'quiet::NoUpdate "true";' >> aptconfig.conf
 	export LC_ALL=C
 	export LC_ALL=C
@@ -170,13 +167,17 @@ getarchitecture() {
 		if [ -n "$ARCH" ]; then
 		if [ -n "$ARCH" ]; then
 			echo $ARCH
 			echo $ARCH
 		else
 		else
-			dpkg-architecture -qDEB_BUILD_ARCH
+			dpkg --print-architecture
 		fi
 		fi
 	else
 	else
 		echo $1
 		echo $1
 	fi
 	fi
 }
 }
 
 
+getarchitectures() {
+	echo "$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')"
+}
+
 configarchitecture() {
 configarchitecture() {
 	local CONFFILE=rootdir/etc/apt/apt.conf.d/01multiarch.conf
 	local CONFFILE=rootdir/etc/apt/apt.conf.d/01multiarch.conf
 	rm -f $CONFFILE
 	rm -f $CONFFILE
@@ -186,6 +187,30 @@ configarchitecture() {
 		echo "APT::Architectures:: \"$(getarchitecture $1)\";" >> $CONFFILE
 		echo "APT::Architectures:: \"$(getarchitecture $1)\";" >> $CONFFILE
 		shift
 		shift
 	done
 	done
+	configdpkg
+}
+
+configdpkg() {
+	if [ ! -e rootdir/var/lib/dpkg/status ]; then
+		local STATUSFILE=$(echo "$(basename $0)" | sed -e 's/^test-/status-/' -e 's/^skip-/status-/')
+		if [ -f "${TESTDIRECTORY}/${STATUSFILE}" ]; then
+			cp "${TESTDIRECTORY}/${STATUSFILE}" rootdir/var/lib/dpkg/status
+		else
+			echo -n > rootdir/var/lib/dpkg/status
+		fi
+	fi
+	if $(which dpkg) --assert-multi-arch; then
+		local ARCHS="$(getarchitectures)"
+		if echo "$ARCHS" | grep -E -q '[^ ]+ [^ ]+'; then
+			DPKGARCH="$(dpkg --print-architecture)"
+			for ARCH in ${ARCHS}; do
+				if [ "${ARCH}" != "${DPKGARCH}" ]; then dpkg --add-architecture ${ARCH}; fi
+			done
+			if [ "0" = "$(dpkg -l dpkg 2> /dev/null | grep '^i' | wc -l)" ]; then
+				insertinstalledpackage 'dpkg' "all" '1.16.2~wipmultiarch~fake'
+			fi
+		fi
+	fi
 }
 }
 
 
 setupsimplenativepackage() {
 setupsimplenativepackage() {
@@ -350,7 +375,7 @@ createaptftparchiveconfig() {
 	local ARCHS="$(find pool/ -name '*.deb' | grep -oE '_[a-z0-9-]+\.deb$' | sort | uniq | sed -e '/^_all.deb$/ d' -e 's#^_\([a-z0-9-]*\)\.deb$#\1#' | tr '\n' ' ')"
 	local ARCHS="$(find pool/ -name '*.deb' | grep -oE '_[a-z0-9-]+\.deb$' | sort | uniq | sed -e '/^_all.deb$/ d' -e 's#^_\([a-z0-9-]*\)\.deb$#\1#' | tr '\n' ' ')"
 	if [ -z "$ARCHS" ]; then
 	if [ -z "$ARCHS" ]; then
 		# the pool is empty, so we will operate on faked packages - let us use the configured archs
 		# the pool is empty, so we will operate on faked packages - let us use the configured archs
-		ARCHS="$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')"
+		ARCHS="$(getarchitectures)"
 	fi
 	fi
 	echo -n 'Dir {
 	echo -n 'Dir {
 	ArchiveDir "' >> ftparchive.conf
 	ArchiveDir "' >> ftparchive.conf
@@ -432,7 +457,7 @@ insertpackage() {
 	local ARCHS=""
 	local ARCHS=""
 	for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
 	for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
 		if [ "$arch" = "all" ]; then
 		if [ "$arch" = "all" ]; then
-			ARCHS="$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')"
+			ARCHS="$(getarchitectures)"
 		else
 		else
 			ARCHS="$arch"
 			ARCHS="$arch"
 		fi
 		fi
@@ -486,7 +511,8 @@ insertinstalledpackage() {
 	local VERSION="$3"
 	local VERSION="$3"
 	local DEPENDENCIES="$4"
 	local DEPENDENCIES="$4"
 	local PRIORITY="${5:-optional}"
 	local PRIORITY="${5:-optional}"
-	local FILE="rootdir/var/lib/dpkg/status"
+	local FILE='rootdir/var/lib/dpkg/status'
+	local INFO='rootdir/var/lib/dpkg/info'
 	for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
 	for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
 		echo "Package: $NAME
 		echo "Package: $NAME
 Status: install ok installed
 Status: install ok installed
@@ -502,6 +528,11 @@ Version: $VERSION" >> $FILE
  YOU did something horribly wrong! They are autogenerated
  YOU did something horribly wrong! They are autogenerated
  und used only by testcases for APT and surf no other propose…
  und used only by testcases for APT and surf no other propose…
 " >> $FILE
 " >> $FILE
+		if [ "$(dpkg-query -W --showformat='${Multi-Arch}')" = 'same' ]; then
+			echo -n > ${INFO}/${NAME}:${arch}.list
+		else
+			echo -n > ${INFO}/${NAME}.list
+		fi
 	done
 	done
 }
 }
 
 
@@ -542,9 +573,6 @@ generatereleasefiles() {
 	# both should be given in notation date/touch can understand
 	# both should be given in notation date/touch can understand
 	msgninfo "\tGenerate Release files… "
 	msgninfo "\tGenerate Release files… "
 	if [ -e aptarchive/dists ]; then
 	if [ -e aptarchive/dists ]; then
-		for dir in $(find ./aptarchive/dists -mindepth 3 -maxdepth 3 -type d -name 'i18n'); do
-			aptftparchive -qq release $dir -o APT::FTPArchive::Release::Patterns::='Translation-*' > $dir/Index
-		done
 		for dir in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do
 		for dir in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do
 			local SUITE="$(echo "$dir" | cut -d'/' -f 4)"
 			local SUITE="$(echo "$dir" | cut -d'/' -f 4)"
 			local CODENAME="$(getcodenamefromsuite $SUITE)"
 			local CODENAME="$(getcodenamefromsuite $SUITE)"

+ 21 - 0
test/integration/skip-avoid-avoiding-breaks-predepends

@@ -0,0 +1,21 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'native'
+
+insertinstalledpackage 'looping' 'native' '1'
+insertinstalledpackage 'loop1' 'native' '1' 'Depends: loop2 (= 1)'
+insertinstalledpackage 'loop2' 'native' '1' 'Depends: loop1 (= 1)'
+
+buildsimplenativepackage 'looping' 'native' '1.15.7.2' 'stable' 'Breaks: loop2 (<= 1)'
+buildsimplenativepackage 'loop1' 'native' '2' 'stable' 'Depends: loop2 (= 2)'
+buildsimplenativepackage 'loop2' 'native' '2' 'stable' 'Depends: loop1 (= 2)
+Pre-Depends: looping (>= 1.15)'
+
+setupaptarchive
+
+aptget dist-upgrade -y -o Debug::pkgOrderList=1 #-qq 2>&1 > /dev/null
+testdpkginstalled looping loop1 loop2

+ 0 - 33
test/integration/status-bug-64141-install-dependencies-for-on-hold

@@ -1,33 +0,0 @@
-Package: apt
-Status: install ok installed
-Priority: important
-Section: admin
-Installed-Size: 6048
-Maintainer: APT Development Team <deity@lists.debian.org>
-Architecture: i386
-Version: 0.8.9
-Provides: libapt-pkg4.10
-Depends: libc6 (>= 2.3.4)
-Description: Advanced front-end for dpkg
-
-Package: libc6
-Status: install ok installed
-Priority: required
-Section: libs
-Installed-Size: 9356
-Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org>
-Architecture: i386
-Source: eglibc
-Version: 2.3.5-7
-Provides: glibc-2.11-1
-Description: Embedded GNU C Library: Shared libraries
-
-Package: oldcrap
-Status: install ok installed
-Priority: extra
-Section: oldlibs
-Installed-Size: 1
-Maintainer: Joe Sixpack <joe@example.org>
-Architecture: all
-Version: 1-1
-Description: Old crappy nothing package

+ 3 - 3
test/integration/test-bug-549968-install-depends-of-not-installed

@@ -14,13 +14,13 @@ setupaptarchive
 
 
 # We check the Markers here as the autoremove nuker will also
 # We check the Markers here as the autoremove nuker will also
 # prevent it, but to late - its better to fail earlier
 # prevent it, but to late - its better to fail earlier
-testequal 'Reading package lists...
+testequal "Reading package lists...
 Building dependency tree...
 Building dependency tree...
   MarkInstall coolstuff [ i386 ] < none -> 1.0 > ( other ) FU=1
   MarkInstall coolstuff [ i386 ] < none -> 1.0 > ( other ) FU=1
     Ignore MarkInstall of extracoolstuff [ i386 ] < none -> 1.0 > ( other ) as its mode (Keep) is protected
     Ignore MarkInstall of extracoolstuff [ i386 ] < none -> 1.0 > ( other ) as its mode (Keep) is protected
-Package extracoolstuff is not installed, so not removed
+Package 'extracoolstuff' is not installed, so not removed
 The following NEW packages will be installed:
 The following NEW packages will be installed:
   coolstuff
   coolstuff
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
 Inst coolstuff (1.0 unstable [all])
 Inst coolstuff (1.0 unstable [all])
-Conf coolstuff (1.0 unstable [all])' aptget install coolstuff extracoolstuff- -o Debug::pkgDepCache::Marker=1 -s
+Conf coolstuff (1.0 unstable [all])" aptget install coolstuff extracoolstuff- -o Debug::pkgDepCache::Marker=1 -s

+ 17 - 6
test/integration/test-bug-612099-multiarch-conflicts

@@ -16,7 +16,7 @@ buildsimplenativepackage 'foobar' 'amd64' '1.0' 'stable' 'Depends: libc6'
 setupaptarchive
 setupaptarchive
 
 
 aptget install libc6:i386 -t stable -y -qq 2>&1 > /dev/null
 aptget install libc6:i386 -t stable -y -qq 2>&1 > /dev/null
-testdpkginstalled libc6
+testdpkginstalled libc6:i386
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
 Reading state information...
 Reading state information...
@@ -75,8 +75,13 @@ The following packages will be upgraded:
 1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
 1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
 Inst libc6 [1.0] (2.0 testing [all])
 Inst libc6 [1.0] (2.0 testing [all])
 Conf libc6 (2.0 testing [all])' aptget upgrade -t testing -s
 Conf libc6 (2.0 testing [all])' aptget upgrade -t testing -s
-aptget upgrade -y -qq 2>&1 > /dev/null
-testdpkginstalled libc6
+# FIXME: on amd64 systems this test wouldn't run with a real upgrade
+# as APT (here i386) disagree about the native architecture, so
+# we fake it here:
+#aptget upgrade -y -qq 2>&1 > /dev/null
+aptget purge libc6 -y -qq 2>&1 >/dev/null
+aptget install libc6:i386 -y -qq 2>&1 >/dev/null
+testdpkginstalled libc6:all
 
 
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
@@ -125,7 +130,7 @@ buildsimplenativepackage 'foobar-same' 'amd64' '1.0' 'stable' 'Depends: libc6-sa
 setupaptarchive
 setupaptarchive
 
 
 aptget install libc6-same:i386 -t stable -y -qq 2>&1 > /dev/null
 aptget install libc6-same:i386 -t stable -y -qq 2>&1 > /dev/null
-testdpkginstalled libc6-same
+testdpkginstalled libc6-same:i386
 
 
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
@@ -168,8 +173,14 @@ The following packages will be upgraded:
 1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
 1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
 Inst libc6-same [1.0] (2.0 testing [all])
 Inst libc6-same [1.0] (2.0 testing [all])
 Conf libc6-same (2.0 testing [all])' aptget upgrade -t testing -s
 Conf libc6-same (2.0 testing [all])' aptget upgrade -t testing -s
-aptget upgrade -y -qq 2>&1 > /dev/null
-testdpkginstalled libc6-same
+# FIXME: on amd64 systems this test wouldn't run with a real upgrade
+# as APT (here i386) disagree about the native architecture, so
+# we fake it here:
+#aptget upgrade -y -qq 2>&1 > /dev/null
+aptget purge libc6-same -y -qq 2>&1 >/dev/null
+aptget install libc6-same:i386 -y -qq 2>&1 >/dev/null
+testdpkginstalled libc6-same:all
+
 
 
 testequal "Reading package lists...
 testequal "Reading package lists...
 Building dependency tree...
 Building dependency tree...

+ 1 - 8
test/integration/test-bug-624218-Translation-file-handling

@@ -42,16 +42,9 @@ msgtest 'Download of nothing if none is forced' 'with Index'
 aptget update -o Acquire::Languages=none | grep -q -e 'Translation' && msgfail || msgpass
 aptget update -o Acquire::Languages=none | grep -q -e 'Translation' && msgfail || msgpass
 rm -rf rootdir/var/lib/apt/lists
 rm -rf rootdir/var/lib/apt/lists
 
 
-sed -i '/i18n\/Index$/ d' $(find aptarchive -name 'Release')
+sed -i '/i18n\/Translation-.*$/ d' $(find aptarchive -name 'Release')
 signreleasefiles
 signreleasefiles
 
 
-# we have to try as not every archive includes the i18n Index in the Release file - if it has one at all
-msgtest 'Download no Translation- if forced language is non-existent' 'with not-announced Index'
-aptget update -o Acquire::Languages=ast_DE | grep -q -e 'Translation-' && msgfail || msgpass
-rm -rf rootdir/var/lib/apt/lists
-
-find aptarchive -name 'Index' -delete
-
 msgtest 'Download of en as forced language' 'without Index'
 msgtest 'Download of en as forced language' 'without Index'
 aptget update -o Acquire::Languages=en | grep -q -e 'Translation-en ' && msgpass || msgfail
 aptget update -o Acquire::Languages=en | grep -q -e 'Translation-en ' && msgpass || msgfail
 rm -rf rootdir/var/lib/apt/lists
 rm -rf rootdir/var/lib/apt/lists

+ 15 - 5
test/integration/test-bug-64141-install-dependencies-for-on-hold

@@ -4,7 +4,19 @@ set -e
 TESTDIR=$(readlink -f $(dirname $0))
 TESTDIR=$(readlink -f $(dirname $0))
 . $TESTDIR/framework
 . $TESTDIR/framework
 setupenvironment
 setupenvironment
-configarchitecture "i386"
+configarchitecture 'native' 'strange-arch'
+
+insertpackage 'unstable' 'unrelated' 'strange-arch' '1'
+
+insertinstalledpackage 'apt' 'native' '0.8.9' 'Depends: libc6 (>= 2.3.4)'
+insertinstalledpackage 'libc6' 'native' '2.4.1-1'
+insertinstalledpackage 'oldcrap' 'all' '1-1'
+
+insertpackage 'unstable' 'apt' 'native' '0.8.10' 'Depends: libc6 (>= 2.10), libdb4.8
+Breaks: oldcrap'
+insertpackage 'unstable' 'libc6' 'native' '2.11.2-7'
+insertpackage 'unstable' 'libdb4.8' 'native' '4.8.30-3'
+
 setupaptarchive
 setupaptarchive
 
 
 testequal 'Reading package lists...
 testequal 'Reading package lists...
@@ -16,11 +28,10 @@ The following NEW packages will be installed:
 The following packages will be upgraded:
 The following packages will be upgraded:
   apt libc6
   apt libc6
 2 upgraded, 1 newly installed, 1 to remove and 0 not upgraded.
 2 upgraded, 1 newly installed, 1 to remove and 0 not upgraded.
-Need to get 0 B/6724 kB of archives.
-After this operation, 1523 kB of additional disk space will be used.
+After this operation, 0 B of additional disk space will be used.
 E: Trivial Only specified but this is not a trivial operation.' aptget dist-upgrade --trivial-only
 E: Trivial Only specified but this is not a trivial operation.' aptget dist-upgrade --trivial-only
 
 
-echo 'apt hold' | dpkg --set-selections
+aptmark hold apt -qq
 
 
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
@@ -29,6 +40,5 @@ The following packages have been kept back:
 The following packages will be upgraded:
 The following packages will be upgraded:
   libc6
   libc6
 1 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
 1 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
-Need to get 0 B/3881 kB of archives.
 After this operation, 0 B of additional disk space will be used.
 After this operation, 0 B of additional disk space will be used.
 E: Trivial Only specified but this is not a trivial operation.' aptget dist-upgrade --trivial-only -o Test='hold-back-apt'
 E: Trivial Only specified but this is not a trivial operation.' aptget dist-upgrade --trivial-only -o Test='hold-back-apt'

+ 29 - 0
test/integration/test-releasefile-verification

@@ -153,6 +153,35 @@ runtest() {
 	installaptold
 	installaptold
 }
 }
 
 
+runtest2() {
+	prepare ${PKGFILE}
+	rm -rf rootdir/var/lib/apt/lists
+	signreleasefiles 'Joe Sixpack'
+	msgtest 'Cold archive signed by' 'Joe Sixpack'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+
+	# New .deb but now an unsigned archive. For example MITM to circumvent
+	# package verification.
+	prepare ${PKGFILE}-new
+	find aptarchive/ -name InRelease -delete
+	find aptarchive/ -name Release.gpg -delete
+	msgtest 'Warm archive signed by' 'nobody'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE}-new)
+" aptcache show apt
+	failaptnew
+
+	# Unsigned archive from the beginning must also be detected.
+	rm -rf rootdir/var/lib/apt/lists
+	msgtest 'Cold archive signed by' 'nobody'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE}-new)
+" aptcache show apt
+	failaptnew
+}
+runtest2
+
+
 DELETEFILE="InRelease"
 DELETEFILE="InRelease"
 runtest
 runtest
 DELETEFILE="Release.gpg"
 DELETEFILE="Release.gpg"

+ 80 - 0
test/integration/test-suggest-installed-multiarch-silbing

@@ -0,0 +1,80 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64' 'i386' 'armel'
+
+insertinstalledpackage 'foo' 'i386' '1'
+insertpackage 'unstable' 'foo' 'amd64,i386' '1'
+
+insertinstalledpackage 'foo2' 'i386' '1'
+insertpackage 'unstable' 'foo2' 'i386' '1'
+
+insertinstalledpackage 'foo3' 'amd64' '1'
+insertpackage 'unstable' 'foo3' 'amd64,i386' '1'
+
+insertinstalledpackage 'samefoo' 'i386,amd64' '1' 'Multi-Arch: same'
+insertpackage 'unstable' 'samefoo' 'amd64,i386,armel' '1' 'Multi-Arch: same'
+
+insertinstalledpackage 'samefoo2' 'i386' '1' 'Multi-Arch: same'
+insertpackage 'unstable' 'samefoo2' 'amd64,i386,armel' '1' 'Multi-Arch: same'
+
+insertinstalledpackage 'mozplugger' 'i386' '1' 'Depends: iceweasel | fireweasel'
+insertinstalledpackage 'fireweasel' 'i386' '1'
+insertpackage 'unstable' 'mozplugger' 'i386,amd64' '1' 'Depends: iceweasel | fireweasel'
+
+setupaptarchive
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'foo' is not installed, so not removed. Did you mean 'foo:i386'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove foo -s
+
+testequal "Reading package lists...
+Building dependency tree...
+The following packages will be REMOVED:
+  foo2:i386
+0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
+Remv foo2:i386 [1]" aptget remove foo2 -s
+
+testequal "Reading package lists...
+Building dependency tree...
+The following packages will be REMOVED:
+  foo3
+0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
+Remv foo3 [1]" aptget remove foo3 -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'foo3:i386' is not installed, so not removed. Did you mean 'foo3'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove foo3:i386 -s
+
+testequalor2 "Reading package lists...
+Building dependency tree...
+Package 'samefoo:armel' is not installed, so not removed. Did you mean 'samefoo'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." "Reading package lists...
+Building dependency tree...
+Package 'samefoo:armel' is not installed, so not removed. Did you mean 'samefoo:i386'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove samefoo:armel -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'samefoo2' is not installed, so not removed. Did you mean 'samefoo2:i386'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove samefoo2 -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'samefoo2:armel' is not installed, so not removed. Did you mean 'samefoo2:i386'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove samefoo2:armel -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'iceweasel' is not installed, so not removed
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove iceweasel -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'fireweasel' is not installed, so not removed. Did you mean 'fireweasel:i386'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove fireweasel:amd64 -s