##################################################################### */
/*}}}*/
// Include Files /*{{{*/
+#include<config.h>
+
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/policy.h>
#include <apt-pkg/version.h>
#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/macros.h>
-#include <apti18n.h>
-
#include <string>
#include <sys/stat.h>
#include <unistd.h>
-
#include <ctype.h>
+
+#include <apti18n.h>
/*}}}*/
using std::string;
Dirty = false;
HeaderSz = sizeof(pkgCache::Header);
+ GroupSz = sizeof(pkgCache::Group);
PackageSz = sizeof(pkgCache::Package);
PackageFileSz = sizeof(pkgCache::PackageFile);
VersionSz = sizeof(pkgCache::Version);
VerFileSz = sizeof(pkgCache::VerFile);
DescFileSz = sizeof(pkgCache::DescFile);
+ GroupCount = 0;
PackageCount = 0;
VersionCount = 0;
DescriptionCount = 0;
StringList = 0;
VerSysName = 0;
Architecture = 0;
- memset(HashTable,0,sizeof(HashTable));
+ memset(PkgHashTable,0,sizeof(PkgHashTable));
+ memset(GrpHashTable,0,sizeof(GrpHashTable));
memset(Pools,0,sizeof(Pools));
+
+ CacheFileSize = 0;
}
/*}}}*/
// Cache::Header::CheckSizes - Check if the two headers have same *sz /*{{{*/
bool pkgCache::Header::CheckSizes(Header &Against) const
{
if (HeaderSz == Against.HeaderSz &&
+ GroupSz == Against.GroupSz &&
PackageSz == Against.PackageSz &&
PackageFileSz == Against.PackageFileSz &&
VersionSz == Against.VersionSz &&
/* */
pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map)
{
+ // call getArchitectures() with cached=false to ensure that the
+ // architectures cache is re-evaulated. this is needed in cases
+ // when the APT::Architecture field changes between two cache creations
+ MultiArchEnabled = APT::Configuration::getArchitectures(false).size() > 1;
if (DoMap == true)
ReMap();
}
// Cache::ReMap - Reopen the cache file /*{{{*/
// ---------------------------------------------------------------------
/* If the file is already closed then this will open it open it. */
-bool pkgCache::ReMap()
+bool pkgCache::ReMap(bool const &Errorchecks)
{
// Apply the typecasts.
HeaderP = (Header *)Map.Data();
+ GrpP = (Group *)Map.Data();
PkgP = (Package *)Map.Data();
VerFileP = (VerFile *)Map.Data();
DescFileP = (DescFile *)Map.Data();
StringItemP = (StringItem *)Map.Data();
StrP = (char *)Map.Data();
+ if (Errorchecks == false)
+ return true;
+
if (Map.Size() == 0 || HeaderP == 0)
return _error->Error(_("Empty package cache"));
HeaderP->CheckSizes(DefHeader) == false)
return _error->Error(_("The package cache file is an incompatible version"));
+ if (Map.Size() < HeaderP->CacheFileSize)
+ return _error->Error(_("The package cache file is corrupted, it is too small"));
+
// Locate our VS..
if (HeaderP->VerSysName == 0 ||
(VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
unsigned long pkgCache::sHash(const string &Str) const
{
unsigned long Hash = 0;
- for (string::const_iterator I = Str.begin(); I != Str.end(); I++)
+ for (string::const_iterator I = Str.begin(); I != Str.end(); ++I)
Hash = 5*Hash + tolower_ascii(*I);
- return Hash % _count(HeaderP->HashTable);
+ return Hash % _count(HeaderP->PkgHashTable);
}
unsigned long pkgCache::sHash(const char *Str) const
{
unsigned long Hash = 0;
- for (const char *I = Str; *I != 0; I++)
+ for (const char *I = Str; *I != 0; ++I)
Hash = 5*Hash + tolower_ascii(*I);
- return Hash % _count(HeaderP->HashTable);
+ return Hash % _count(HeaderP->PkgHashTable);
}
/*}}}*/
-// Cache::FindPkg - Locate a package by name /*{{{*/
+// Cache::SingleArchFindPkg - Locate a package by name /*{{{*/
// ---------------------------------------------------------------------
-/* Returns 0 on error, pointer to the package otherwise */
-pkgCache::PkgIterator pkgCache::FindPkg(const string &Name)
+/* Returns 0 on error, pointer to the package otherwise
+ The multiArch enabled methods will fallback to this one as it is (a bit)
+ faster for single arch environments and realworld is mostly singlearch… */
+pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name)
{
// Look at the hash bucket
- Package *Pkg = PkgP + HeaderP->HashTable[Hash(Name)];
+ Package *Pkg = PkgP + HeaderP->PkgHashTable[Hash(Name)];
for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
{
if (Pkg->Name != 0 && StrP[Pkg->Name] == Name[0] &&
- stringcasecmp(Name,StrP + Pkg->Name) == 0)
- return PkgIterator(*this,Pkg);
+ stringcasecmp(Name,StrP + Pkg->Name) == 0)
+ return PkgIterator(*this,Pkg);
}
return PkgIterator(*this,0);
}
/*}}}*/
+// Cache::FindPkg - Locate a package by name /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns 0 on error, pointer to the package otherwise */
+pkgCache::PkgIterator pkgCache::FindPkg(const string &Name) {
+ size_t const found = Name.find(':');
+ if (found == string::npos)
+ {
+ if (MultiArchCache() == false)
+ return SingleArchFindPkg(Name);
+ else
+ return FindPkg(Name, "native");
+ }
+ string const Arch = Name.substr(found+1);
+ /* Beware: This is specialcased to handle pkg:any in dependencies as
+ these are linked to virtual pkg:any named packages with all archs.
+ If you want any arch from a given pkg, use FindPkg(pkg,arch) */
+ if (Arch == "any")
+ return FindPkg(Name, "any");
+ return FindPkg(Name.substr(0, found), Arch);
+}
+ /*}}}*/
+// Cache::FindPkg - Locate a package by name /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns 0 on error, pointer to the package otherwise */
+pkgCache::PkgIterator pkgCache::FindPkg(const string &Name, string const &Arch) {
+ if (MultiArchCache() == false) {
+ if (Arch == "native" || Arch == "all" || Arch == "any" ||
+ Arch == NativeArch())
+ return SingleArchFindPkg(Name);
+ else
+ return PkgIterator(*this,0);
+ }
+ /* We make a detour via the GrpIterator here as
+ on a multi-arch environment a group is easier to
+ find than a package (less entries in the buckets) */
+ pkgCache::GrpIterator Grp = FindGrp(Name);
+ if (Grp.end() == true)
+ return PkgIterator(*this,0);
+
+ return Grp.FindPkg(Arch);
+}
+ /*}}}*/
+// Cache::FindGrp - Locate a group by name /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns End-Pointer on error, pointer to the group otherwise */
+pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) {
+ if (unlikely(Name.empty() == true))
+ return GrpIterator(*this,0);
+
+ // Look at the hash bucket for the group
+ Group *Grp = GrpP + HeaderP->GrpHashTable[sHash(Name)];
+ for (; Grp != GrpP; Grp = GrpP + Grp->Next) {
+ if (Grp->Name != 0 && StrP[Grp->Name] == Name[0] &&
+ stringcasecmp(Name, StrP + Grp->Name) == 0)
+ return GrpIterator(*this, Grp);
+ }
+
+ return GrpIterator(*this,0);
+}
+ /*}}}*/
// Cache::CompTypeDeb - Return a string describing the compare type /*{{{*/
// ---------------------------------------------------------------------
/* This returns a string representation of the dependency compare
return 0;
}
/*}}}*/
-// Bases for iterator classes /*{{{*/
-void pkgCache::VerIterator::_dummy() {}
-void pkgCache::DepIterator::_dummy() {}
-void pkgCache::PrvIterator::_dummy() {}
-void pkgCache::DescIterator::_dummy() {}
+// GrpIterator::FindPkg - Locate a package by arch /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns an End-Pointer on error, pointer to the package otherwise */
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const {
+ if (unlikely(IsGood() == false || S->FirstPackage == 0))
+ return PkgIterator(*Owner, 0);
+
+ /* If we accept any package we simply return the "first"
+ package in this group (the last one added). */
+ if (Arch == "any")
+ return PkgIterator(*Owner, Owner->PkgP + S->FirstPackage);
+
+ char const* const myArch = Owner->NativeArch();
+ /* Most of the time the package for our native architecture is
+ the one we add at first to the cache, but this would be the
+ last one we check, so we do it now. */
+ if (Arch == "native" || Arch == myArch || Arch == "all") {
+ pkgCache::Package *Pkg = Owner->PkgP + S->LastPackage;
+ if (strcasecmp(myArch, Owner->StrP + Pkg->Arch) == 0)
+ return PkgIterator(*Owner, Pkg);
+ Arch = myArch;
+ }
+
+ /* Iterate over the list to find the matching arch
+ unfortunately this list includes "package noise"
+ (= different packages with same calculated hash),
+ so we need to check the name also */
+ for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP;
+ Pkg = Owner->PkgP + Pkg->NextPackage) {
+ if (S->Name == Pkg->Name &&
+ stringcasecmp(Arch, Owner->StrP + Pkg->Arch) == 0)
+ return PkgIterator(*Owner, Pkg);
+ if ((Owner->PkgP + S->LastPackage) == Pkg)
+ break;
+ }
+
+ return PkgIterator(*Owner, 0);
+}
+ /*}}}*/
+// GrpIterator::FindPreferredPkg - Locate the "best" package /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns an End-Pointer on error, pointer to the package otherwise */
+pkgCache::PkgIterator pkgCache::GrpIterator::FindPreferredPkg(bool const &PreferNonVirtual) const {
+ pkgCache::PkgIterator Pkg = FindPkg("native");
+ if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
+ return Pkg;
+
+ std::vector<std::string> const archs = APT::Configuration::getArchitectures();
+ for (std::vector<std::string>::const_iterator a = archs.begin();
+ a != archs.end(); ++a) {
+ Pkg = FindPkg(*a);
+ if (Pkg.end() == false && (PreferNonVirtual == false || Pkg->VersionList != 0))
+ return Pkg;
+ }
+
+ if (PreferNonVirtual == true)
+ return FindPreferredPkg(false);
+ return PkgIterator(*Owner, 0);
+}
+ /*}}}*/
+// GrpIterator::NextPkg - Locate the next package in the group /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns an End-Pointer on error, pointer to the package otherwise.
+ We can't simply ++ to the next as the next package of the last will
+ be from a different group (with the same hash value) */
+pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const &LastPkg) const {
+ if (unlikely(IsGood() == false || S->FirstPackage == 0 ||
+ LastPkg.end() == true))
+ return PkgIterator(*Owner, 0);
+
+ if (S->LastPackage == LastPkg.Index())
+ return PkgIterator(*Owner, 0);
+
+ return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage);
+}
+ /*}}}*/
+// GrpIterator::operator ++ - Postfix incr /*{{{*/
+// ---------------------------------------------------------------------
+/* This will advance to the next logical group in the hash table. */
+void pkgCache::GrpIterator::operator ++(int)
+{
+ // Follow the current links
+ if (S != Owner->GrpP)
+ S = Owner->GrpP + S->Next;
+
+ // Follow the hash table
+ while (S == Owner->GrpP && (HashIndex+1) < (signed)_count(Owner->HeaderP->GrpHashTable))
+ {
+ HashIndex++;
+ S = Owner->GrpP + Owner->HeaderP->GrpHashTable[HashIndex];
+ }
+};
/*}}}*/
// PkgIterator::operator ++ - Postfix incr /*{{{*/
// ---------------------------------------------------------------------
void pkgCache::PkgIterator::operator ++(int)
{
// Follow the current links
- if (Pkg != Owner->PkgP)
- Pkg = Owner->PkgP + Pkg->NextPackage;
+ if (S != Owner->PkgP)
+ S = Owner->PkgP + S->NextPackage;
// Follow the hash table
- while (Pkg == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->HashTable))
+ while (S == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->PkgHashTable))
{
HashIndex++;
- Pkg = Owner->PkgP + Owner->HeaderP->HashTable[HashIndex];
+ S = Owner->PkgP + Owner->HeaderP->PkgHashTable[HashIndex];
}
};
/*}}}*/
/* By this we mean if it is either cleanly installed or cleanly removed. */
pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
{
- if (Pkg->InstState == pkgCache::State::ReInstReq ||
- Pkg->InstState == pkgCache::State::HoldReInstReq)
+ if (S->InstState == pkgCache::State::ReInstReq ||
+ S->InstState == pkgCache::State::HoldReInstReq)
return NeedsUnpack;
- if (Pkg->CurrentState == pkgCache::State::UnPacked ||
- Pkg->CurrentState == pkgCache::State::HalfConfigured)
+ if (S->CurrentState == pkgCache::State::UnPacked ||
+ S->CurrentState == pkgCache::State::HalfConfigured)
// we leave triggers alone complettely. dpkg deals with
// them in a hard-to-predict manner and if they get
// resolved by dpkg before apt run dpkg --configure on
//Pkg->CurrentState == pkgCache::State::TriggersPending)
return NeedsConfigure;
- if (Pkg->CurrentState == pkgCache::State::HalfInstalled ||
- Pkg->InstState != pkgCache::State::Ok)
+ if (S->CurrentState == pkgCache::State::HalfInstalled ||
+ S->InstState != pkgCache::State::Ok)
return NeedsUnpack;
return NeedsNothing;
if they provide no new information (e.g. there is no newer version than candidate)
If no version and/or section can be found "none" is used. */
std::ostream&
-operator<<(ostream& out, pkgCache::PkgIterator Pkg)
+operator<<(std::ostream& out, pkgCache::PkgIterator Pkg)
{
if (Pkg.end() == true)
return out << "invalid package";
string candidate = string(Pkg.CandVersion() == 0 ? "none" : Pkg.CandVersion());
string newest = string(Pkg.VersionList().end() ? "none" : Pkg.VersionList().VerStr());
- out << Pkg.Name() << " < " << current;
+ out << Pkg.Name() << " [ " << Pkg.Arch() << " ] < " << current;
if (current != candidate)
out << " -> " << candidate;
if ( newest != "none" && candidate != newest)
return out;
}
/*}}}*/
+// PkgIterator::FullName - Returns Name and (maybe) Architecture /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns a name:arch string */
+std::string pkgCache::PkgIterator::FullName(bool const &Pretty) const
+{
+ string fullname = Name();
+ if (Pretty == false ||
+ (strcmp(Arch(), "all") != 0 &&
+ strcmp(Owner->NativeArch(), Arch()) != 0))
+ return fullname.append(":").append(Arch());
+ return fullname;
+}
+ /*}}}*/
// DepIterator::IsCritical - Returns true if the dep is important /*{{{*/
// ---------------------------------------------------------------------
/* Currently critical deps are defined as depends, predepends and
conflicts (including dpkg's Breaks fields). */
-bool pkgCache::DepIterator::IsCritical()
+bool pkgCache::DepIterator::IsCritical() const
{
- if (Dep->Type == pkgCache::Dep::Conflicts ||
- Dep->Type == pkgCache::Dep::DpkgBreaks ||
- Dep->Type == pkgCache::Dep::Obsoletes ||
- Dep->Type == pkgCache::Dep::Depends ||
- Dep->Type == pkgCache::Dep::PreDepends)
+ if (IsNegative() == true ||
+ S->Type == pkgCache::Dep::Depends ||
+ S->Type == pkgCache::Dep::PreDepends)
return true;
return false;
}
/*}}}*/
+// DepIterator::IsNegative - Returns true if the dep is a negative one /*{{{*/
+// ---------------------------------------------------------------------
+/* Some dependencies are positive like Depends and Recommends, others
+ are negative like Conflicts which can and should be handled differently */
+bool pkgCache::DepIterator::IsNegative() const
+{
+ return S->Type == Dep::DpkgBreaks ||
+ S->Type == Dep::Conflicts ||
+ S->Type == Dep::Obsoletes;
+}
+ /*}}}*/
// DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/
// ---------------------------------------------------------------------
/* This intellegently looks at dep target packages and tries to figure
In Conjunction with the DepCache the value of Result may not be
super-good since the policy may have made it uninstallable. Using
AllTargets is better in this case. */
-bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
+bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result) const
{
Result = TargetPkg();
virtual package libc-dev which is provided by libc5-dev and libc6-dev
we must ignore libc5-dev when considering the provides list. */
PrvIterator PStart = Result.ProvidesList();
- for (; PStart.end() != true && PStart.OwnerPkg() == ParentPkg(); PStart++);
+ for (; PStart.end() != true && PStart.OwnerPkg() == ParentPkg(); ++PStart);
// Nothing but indirect self provides
if (PStart.end() == true)
// Check for single packages in the provides list
PrvIterator P = PStart;
- for (; P.end() != true; P++)
+ for (; P.end() != true; ++P)
{
// Skip over self provides
if (P.OwnerPkg() == ParentPkg())
provides. It includes every possible package-version that could satisfy
the dependency. The last item in the list has a 0. The resulting pointer
must be delete [] 'd */
-pkgCache::Version **pkgCache::DepIterator::AllTargets()
+pkgCache::Version **pkgCache::DepIterator::AllTargets() const
{
Version **Res = 0;
unsigned long Size =0;
PkgIterator DPkg = TargetPkg();
// Walk along the actual package providing versions
- for (VerIterator I = DPkg.VersionList(); I.end() == false; I++)
+ for (VerIterator I = DPkg.VersionList(); I.end() == false; ++I)
{
- if (Owner->VS->CheckDep(I.VerStr(),Dep->CompareOp,TargetVer()) == false)
+ if (Owner->VS->CheckDep(I.VerStr(),S->CompareOp,TargetVer()) == false)
continue;
- if ((Dep->Type == pkgCache::Dep::Conflicts ||
- Dep->Type == pkgCache::Dep::DpkgBreaks ||
- Dep->Type == pkgCache::Dep::Obsoletes) &&
+ if (IsNegative() == true &&
ParentPkg() == I.ParentPkg())
continue;
}
// Follow all provides
- for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; I++)
+ for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; ++I)
{
- if (Owner->VS->CheckDep(I.ProvideVersion(),Dep->CompareOp,TargetVer()) == false)
+ if (Owner->VS->CheckDep(I.ProvideVersion(),S->CompareOp,TargetVer()) == false)
continue;
- if ((Dep->Type == pkgCache::Dep::Conflicts ||
- Dep->Type == pkgCache::Dep::DpkgBreaks ||
- Dep->Type == pkgCache::Dep::Obsoletes) &&
- ParentPkg() == I.OwnerPkg())
+ if (IsNegative() == true &&
+ ParentPkg()->Group == I.OwnerPkg()->Group)
continue;
Size++;
End = *this;
for (bool LastOR = true; end() == false && LastOR == true;)
{
- LastOR = (Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
+ LastOR = (S->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
(*this)++;
if (LastOR == true)
End = (*this);
}
}
/*}}}*/
+// ostream operator to handle string representation of a dependecy /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+std::ostream& operator<<(std::ostream& out, pkgCache::DepIterator D)
+{
+ if (D.end() == true)
+ return out << "invalid dependency";
+
+ pkgCache::PkgIterator P = D.ParentPkg();
+ pkgCache::PkgIterator T = D.TargetPkg();
+
+ out << (P.end() ? "invalid pkg" : P.FullName(false)) << " " << D.DepType()
+ << " on ";
+ if (T.end() == true)
+ out << "invalid pkg";
+ else
+ out << T;
+
+ if (D->Version != 0)
+ out << " (" << D.CompType() << " " << D.TargetVer() << ")";
+
+ return out;
+}
+ /*}}}*/
// VerIterator::CompareVer - Fast version compare for same pkgs /*{{{*/
// ---------------------------------------------------------------------
/* This just looks over the version list to see if B is listed before A. In
/* Start at A and look for B. If B is found then A > B otherwise
B was before A so A < B */
VerIterator I = *this;
- for (;I.end() == false; I++)
+ for (;I.end() == false; ++I)
if (I == B)
return 1;
return -1;
bool pkgCache::VerIterator::Downloadable() const
{
VerFileIterator Files = FileList();
- for (; Files.end() == false; Files++)
+ for (; Files.end() == false; ++Files)
if ((Files.File()->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource)
return true;
return false;
bool pkgCache::VerIterator::Automatic() const
{
VerFileIterator Files = FileList();
- for (; Files.end() == false; Files++)
+ for (; Files.end() == false; ++Files)
+ // Do not check ButAutomaticUpgrades here as it is kind of automatic…
if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic)
return true;
return false;
{
VerFileIterator Files = FileList();
VerFileIterator Highest = Files;
- for (; Files.end() == false; Files++)
+ for (; Files.end() == false; ++Files)
{
if (Owner->VS->CmpReleaseVer(Files.File().Version(),Highest.File().Version()) > 0)
Highest = Files;
// ---------------------------------------------------------------------
/* This describes the version from a release-centric manner. The output is a
list of Label:Version/Archive */
-string pkgCache::VerIterator::RelStr()
+string pkgCache::VerIterator::RelStr() const
{
bool First = true;
string Res;
- for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; I++)
+ for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
{
// Do not print 'not source' entries'
pkgCache::PkgFileIterator File = I.File();
// See if we have already printed this out..
bool Seen = false;
- for (pkgCache::VerFileIterator J = this->FileList(); I != J; J++)
+ for (pkgCache::VerFileIterator J = this->FileList(); I != J; ++J)
{
pkgCache::PkgFileIterator File2 = J.File();
if (File2->Label == 0 || File->Label == 0)
else
Res += File.Site();
}
- }
+ }
+ if (S->ParentPkg != 0)
+ Res.append(" [").append(Arch()).append("]");
return Res;
}
/*}}}*/
if (stat(FileName(),&Buf) != 0)
return false;
- if (Buf.st_size != (signed)File->Size || Buf.st_mtime != File->mtime)
+ if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime)
return false;
return true;
Res = Res + (Res.empty() == true?"l=":",l=") + Label();
if (Component() != 0)
Res = Res + (Res.empty() == true?"c=":",c=") + Component();
+ if (Architecture() != 0)
+ Res = Res + (Res.empty() == true?"b=":",b=") + Architecture();
return Res;
}
/*}}}*/
{
std::vector<string> const lang = APT::Configuration::getLanguages();
for (std::vector<string>::const_iterator l = lang.begin();
- l != lang.end(); l++)
+ l != lang.end(); ++l)
{
- pkgCache::DescIterator DescDefault = DescriptionList();
- pkgCache::DescIterator Desc = DescDefault;
-
- for (; Desc.end() == false; Desc++)
+ pkgCache::DescIterator Desc = DescriptionList();
+ for (; Desc.end() == false; ++Desc)
if (*l == Desc.LanguageCode())
break;
- if (Desc.end() == true)
- Desc = DescDefault;
+ if (Desc.end() == true)
+ {
+ if (*l == "en")
+ {
+ Desc = DescriptionList();
+ for (; Desc.end() == false; ++Desc)
+ if (strcmp(Desc.LanguageCode(), "") == 0)
+ break;
+ if (Desc.end() == true)
+ continue;
+ }
+ else
+ continue;
+ }
return Desc;
}
-
+ for (pkgCache::DescIterator Desc = DescriptionList();
+ Desc.end() == false; ++Desc)
+ if (strcmp(Desc.LanguageCode(), "") == 0)
+ return Desc;
return DescriptionList();
};