Browse Source

Sync

Author: jgg
Date: 1998-07-07 04:17:00 GMT
Sync
debian/1.8.y
Arch Librarian 19 years ago
parent
commit
6c139d6e36
  1. 732
      apt-pkg/algorithms.cc
  2. 91
      apt-pkg/algorithms.h
  3. 21
      apt-pkg/cacheiterators.h
  4. 137
      apt-pkg/contrib/configuration.cc
  5. 61
      apt-pkg/contrib/configuration.h
  6. 74
      apt-pkg/contrib/error.cc
  7. 15
      apt-pkg/contrib/error.h
  8. 5
      apt-pkg/contrib/fileutl.cc
  9. 6
      apt-pkg/contrib/fileutl.h
  10. 6
      apt-pkg/contrib/mmap.cc
  11. 6
      apt-pkg/contrib/mmap.h
  12. 343
      apt-pkg/contrib/strutl.cc
  13. 36
      apt-pkg/contrib/strutl.h
  14. 90
      apt-pkg/deb/deblistparser.cc
  15. 903
      apt-pkg/depcache.cc
  16. 189
      apt-pkg/depcache.h
  17. 829
      apt-pkg/orderlist.cc
  18. 123
      apt-pkg/orderlist.h
  19. 548
      apt-pkg/packagemanager.cc
  20. 84
      apt-pkg/packagemanager.h
  21. 24
      apt-pkg/pkgcache.cc
  22. 42
      apt-pkg/pkgcache.h
  23. 6
      apt-pkg/pkgcachegen.cc
  24. 6
      apt-pkg/pkgcachegen.h
  25. 465
      apt-pkg/sourcelist.cc
  26. 78
      apt-pkg/sourcelist.h
  27. 6
      apt-pkg/tagfile.cc
  28. 6
      apt-pkg/tagfile.h
  29. 18
      apt-pkg/version.cc
  30. 6
      apt-pkg/version.h

732
apt-pkg/algorithms.cc

@ -0,0 +1,732 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: algorithms.cc,v 1.1 1998/07/07 04:17:00 jgg Exp $
/* ######################################################################
Algorithms - A set of misc algorithms
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
#ifdef __GNUG__
#pragma implementation "pkglib/algorithms.h"
#endif
#include <pkglib/algorithms.h>
#include <pkglib/error.h>
#include <pkglib/pkgelement.h>
#include <iostream.h>
/*}}}*/
pkgProblemResolver *pkgProblemResolver::This = 0;
// Simulate::Simulate - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
pkgSimulate::pkgSimulate(pkgDepCache &Cache) : pkgPackageManager(Cache),
Sim(true,true)
{
Flags = new unsigned char[Cache.HeaderP->PackageCount];
memset(Flags,0,sizeof(*Flags)*Cache.HeaderP->PackageCount);
}
/*}}}*/
// Simulate::Install - Simulate unpacking of a package /*{{{*/
// ---------------------------------------------------------------------
/* */
bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
{
// Adapt the iterator
PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
Flags[Pkg->ID] = 1;
cout << "Inst " << Pkg.Name();
Sim.MarkInstall(Pkg,false);
// Look for broken conflicts+predepends.
for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
{
if (Sim[I].InstallVer == 0)
continue;
for (DepIterator D = Sim[I].InstVerIter(Sim).DependsList(); D.end() == false; D++)
if (D->Type == pkgDEP_Conflicts || D->Type == pkgDEP_PreDepends)
{
if ((Sim[D] & pkgDepCache::DepInstall) == 0)
{
cout << " [" << I.Name() << " on " << D.TargetPkg().Name() << ']';
if (D->Type == pkgDEP_Conflicts)
_error->Error("Fatal, conflicts violated %s",I.Name());
}
}
}
if (Sim.BrokenCount() != 0)
ShortBreaks();
else
cout << endl;
return true;
}
/*}}}*/
// Simulate::Configure - Simulate configuration of a Package /*{{{*/
// ---------------------------------------------------------------------
/* This is not an acurate simulation of relatity, we should really not
install the package.. For some investigations it may be necessary
however. */
bool pkgSimulate::Configure(PkgIterator iPkg)
{
// Adapt the iterator
PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
Flags[Pkg->ID] = 2;
// Sim.MarkInstall(Pkg,false);
if (Sim[Pkg].InstBroken() == true)
{
cout << "Conf " << Pkg.Name() << " broken" << endl;
Sim.Update();
// Print out each package and the failed dependencies
for (pkgCache::DepIterator D = Sim[Pkg].InstVerIter(Sim).DependsList(); D.end() == false; D++)
{
if (Sim.IsImportantDep(D) == false ||
(Sim[D] & pkgDepCache::DepInstall) != 0)
continue;
if (D->Type == pkgDEP_Conflicts)
cout << " Conflicts:" << D.TargetPkg().Name();
else
cout << " Depends:" << D.TargetPkg().Name();
}
cout << endl;
_error->Error("Conf Broken %s",Pkg.Name());
}
else
cout << "Conf " << Pkg.Name();
if (Sim.BrokenCount() != 0)
ShortBreaks();
else
cout << endl;
return true;
}
/*}}}*/
// Simulate::Remove - Simulate the removal of a package /*{{{*/
// ---------------------------------------------------------------------
/* */
bool pkgSimulate::Remove(PkgIterator iPkg)
{
// Adapt the iterator
PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
Flags[Pkg->ID] = 3;
Sim.MarkDelete(Pkg);
cout << "Remv " << Pkg.Name();
if (Sim.BrokenCount() != 0)
ShortBreaks();
else
cout << endl;
return true;
}
/*}}}*/
// Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
// ---------------------------------------------------------------------
/* */
void pkgSimulate::ShortBreaks()
{
cout << " [";
for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
{
if (Sim[I].InstBroken() == true)
{
if (Flags[I->ID] == 0)
cout << I.Name() << ' ';
/* else
cout << I.Name() << "! ";*/
}
}
cout << ']' << endl;
}
/*}}}*/
// ApplyStatus - Adjust for non-ok packages /*{{{*/
// ---------------------------------------------------------------------
/* We attempt to change the state of the all packages that have failed
installation toward their real state. The ordering code will perform
the necessary calculations to deal with the problems. */
bool pkgApplyStatus(pkgDepCache &Cache)
{
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
switch (I->CurrentState)
{
// This means installation failed somehow
case pkgSTATE_UnPacked:
case pkgSTATE_HalfConfigured:
Cache.MarkKeep(I);
break;
// This means removal failed
case pkgSTATE_HalfInstalled:
Cache.MarkDelete(I);
break;
default:
if (I->InstState != pkgSTATE_Ok)
return _error->Error("The package %s is not ok and I "
"don't know how to fix it!",I.Name());
}
}
return true;
}
/*}}}*/
// FixBroken - Fix broken packages /*{{{*/
// ---------------------------------------------------------------------
/* This autoinstalls every broken package and then runs ScoredFix on the
result. */
bool pkgFixBroken(pkgDepCache &Cache)
{
// Auto upgrade all broken packages
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
if (Cache[I].NowBroken() == true)
Cache.MarkInstall(I,true);
/* Fix packages that are in a NeedArchive state but don't have a
downloadable install version */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
if (I.State() != pkgCache::PkgIterator::NeedsUnpack ||
Cache[I].Delete() == true)
continue;
if ((Cache[I].InstVerIter(Cache).File()->Flags & pkgFLAG_NotSource) == 0)
continue;
Cache.MarkInstall(I,true);
}
pkgProblemResolver Fix(Cache);
return Fix.Resolve(true);
}
/*}}}*/
// DistUpgrade - Distribution upgrade /*{{{*/
// ---------------------------------------------------------------------
/* This autoinstalls every package and then force installs every
pre-existing package. This creates the initial set of conditions which
most likely contain problems because too many things were installed.
ScoredFix is used to resolve the problems.
*/
bool pkgDistUpgrade(pkgDepCache &Cache)
{
/* Auto upgrade all installed packages, this provides the basis
for the installation */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
if (I->CurrentVer != 0)
Cache.MarkInstall(I,true);
/* Now, auto upgrade all essential packages - this ensures that
the essential packages are present and working */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
if ((I->Flags & pkgFLAG_Essential) == pkgFLAG_Essential)
Cache.MarkInstall(I,true);
/* We do it again over all previously installed packages to force
conflict resolution on them all. */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
if (I->CurrentVer != 0)
Cache.MarkInstall(I,false);
pkgProblemResolver Fix(Cache);
// Hold back held packages.
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
if (I->SelectedState == pkgSTATE_Hold)
{
Fix.Protect(I);
Cache.MarkKeep(I);
}
}
return Fix.Resolve();
}
/*}}}*/
// ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
pkgProblemResolver::pkgProblemResolver(pkgDepCache &Cache) : Cache(Cache)
{
// Allocate memory
unsigned long Size = Cache.HeaderP->PackageCount;
Scores = new signed short[Size];
Flags = new unsigned char[Size];
memset(Flags,0,sizeof(*Flags)*Size);
// Set debug to true to see its decision logic
Debug = false;
}
/*}}}*/
// ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
// ---------------------------------------------------------------------
/* */
int pkgProblemResolver::ScoreSort(const void *a,const void *b)
{
Package const **A = (Package const **)a;
Package const **B = (Package const **)b;
if (This->Scores[(*A)->ID] > This->Scores[(*B)->ID])
return -1;
if (This->Scores[(*A)->ID] < This->Scores[(*B)->ID])
return 1;
return 0;
}
/*}}}*/
// ProblemResolver::MakeScores - Make the score table /*{{{*/
// ---------------------------------------------------------------------
/* */
void pkgProblemResolver::MakeScores()
{
unsigned long Size = Cache.HeaderP->PackageCount;
memset(Scores,0,sizeof(*Scores)*Size);
// Generate the base scores for a package based on its properties
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
if (Cache[I].InstallVer == 0)
continue;
signed short &Score = Scores[I->ID];
/* This is arbitary, it should be high enough to elevate an
essantial package above most other packages but low enough
to allow an obsolete essential packages to be removed by
a conflicts on a powerfull normal package (ie libc6) */
if ((I->Flags & pkgFLAG_Essential) == pkgFLAG_Essential)
Score += 100;
// We transform the priority
// Important Required Standard Optional Extra
signed short PrioMap[] = {0,3,2,1,-1,-2};
if (Cache[I].InstVerIter(Cache)->Priority <= 5)
Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
/* This helps to fix oddball problems with conflicting packages
on the same level. We enhance the score of installed packages */
if (I->CurrentVer != 0)
Score += 1;
}
// Now that we have the base scores we go and propogate dependencies
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
if (Cache[I].InstallVer == 0)
continue;
for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
{
if (D->Type == pkgDEP_Depends || D->Type == pkgDEP_PreDepends)
Scores[D.TargetPkg()->ID]++;
}
}
// Copy the scores to advoid additive looping
signed short *OldScores = new signed short[Size];
memcpy(OldScores,Scores,sizeof(*Scores)*Size);
/* Now we cause 1 level of dependency inheritance, that is we add the
score of the packages that depend on the target Package. This
fortifies high scoring packages */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
if (Cache[I].InstallVer == 0)
continue;
for (pkgCache::DepIterator D = I.RevDependsList(); D.end() == false; D++)
{
// Only do it for the install version
if ((pkgCache::Version *)D.ParentVer() != Cache[D.ParentPkg()].InstallVer ||
(D->Type != pkgDEP_Depends && D->Type != pkgDEP_PreDepends))
continue;
Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]);
}
}
/* Now we propogate along provides. This makes the packages that
provide important packages extremely important */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
for (pkgCache::PrvIterator P = I.ProvidesList(); P.end() == false; P++)
{
// Only do it once per package
if ((pkgCache::Version *)P.OwnerVer() != Cache[P.OwnerPkg()].InstallVer)
continue;
Scores[P.OwnerPkg()->ID] += abs(Scores[I->ID] - OldScores[I->ID]);
}
}
/* Protected things are pushed really high up. This number should put them
ahead of everything */
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
if ((Flags[I->ID] & Protected) != 0)
Scores[I->ID] += 10000;
delete [] OldScores;
}
/*}}}*/
// ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
// ---------------------------------------------------------------------
/* This goes through and tries to reinstall packages to make this package
installable */
bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
{
if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
return false;
Flags[Pkg->ID] &= ~Upgradable;
bool WasKept = Cache[Pkg].Keep();
Cache.MarkInstall(Pkg,false);
// Isolate the problem dependency
bool Fail = false;
for (pkgCache::DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); D.end() == false;)
{
// Compute a single dependency element (glob or)
pkgCache::DepIterator Start = D;
pkgCache::DepIterator End = D;
unsigned char State = 0;
for (bool LastOR = true; D.end() == false && LastOR == true; D++)
{
State |= Cache[D];
LastOR = (D->CompareOp & pkgOP_OR) == pkgOP_OR;
if (LastOR == true)
End = D;
}
// We only worry about critical deps.
if (End.IsCritical() != true)
continue;
// Dep is ok
if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
continue;
// Hm, the group is broken.. I have no idea how to handle this
if (Start != End)
{
cout << "Note, a broken or group was found in " << Pkg.Name() << "." << endl;
Fail = true;
break;
}
// Upgrade the package if the candidate version will fix the problem.
if ((Cache[Start] & pkgDepCache::DepCVer) == pkgDepCache::DepCVer)
{
PkgIterator P = Start.SmartTargetPkg();
if (DoUpgrade(P) == false)
{
if (Debug == true)
cout << " Reinst Failed because of " << P.Name() << endl;
Fail = true;
break;
}
}
else
{
/* We let the algorithm deal with conflicts on its next iteration,
it is much smarter than us */
if (End->Type == pkgDEP_Conflicts)
continue;
if (Debug == true)
cout << " Reinst Failed early because of " << Start.TargetPkg().Name() << endl;
Fail = true;
break;
}
}
// Undo our operations - it might be smart to undo everything this did..
if (Fail == true)
{
if (WasKept == true)
Cache.MarkKeep(Pkg);
else
Cache.MarkDelete(Pkg);
return false;
}
if (Debug == true)
cout << " Re-Instated " << Pkg.Name() << endl;
return true;
}
/*}}}*/
// ProblemResolver::Resolve - Run the resolution pass /*{{{*/
// ---------------------------------------------------------------------
/* This routines works by calculating a score for each package. The score
is derived by considering the package's priority and all reverse
dependents giving an integer that reflects the amount of breakage that
adjusting the package will inflict.
It goes from highest score to lowest and corrects all of the breaks by
keeping or removing the dependant packages. If that fails then it removes
the package itself and goes on. The routine should be able to intelligently
go from any broken state to a fixed state.
The BrokenFix flag enables a mode where the algorithm tries to
upgrade packages to advoid problems. */
bool pkgProblemResolver::Resolve(bool BrokenFix)
{
unsigned long Size = Cache.HeaderP->PackageCount;
// Record which packages are marked for install
bool Again = false;
do
{
Again = false;
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
{
if (Cache[I].Install() == true)
Flags[I->ID] |= PreInstalled;
else
{
if (Cache[I].InstBroken() == true && BrokenFix == true)
{
Cache.MarkInstall(I,false);
if (Cache[I].Install() == true)
Again = true;
}
Flags[I->ID] &= ~PreInstalled;
}
Flags[I->ID] |= Upgradable;
}
}
while (Again == true);
if (Debug == true)
cout << "Starting" << endl;
MakeScores();
/* We have to order the packages so that the broken fixing pass
operates from highest score to lowest. This prevents problems when
high score packages cause the removal of lower score packages that
would cause the removal of even lower score packages. */
pkgCache::Package **PList = new pkgCache::Package *[Size];
pkgCache::Package **PEnd = PList;
for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
*PEnd++ = I;
This = this;
qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
/* for (pkgCache::Package **K = PList; K != PEnd; K++)
if (Scores[(*K)->ID] != 0)
{
pkgCache::PkgIterator Pkg(Cache,*K);
cout << Scores[(*K)->ID] << ' ' << Pkg.Name() <<
' ' << (pkgCache::Version *)Pkg.CurrentVer() << ' ' <<
Cache[Pkg].InstallVer << ' ' << Cache[Pkg].CandidateVer << endl;
} */
if (Debug == true)
cout << "Starting 2" << endl;
/* Now consider all broken packages. For each broken package we either
remove the package or fix it's problem. We do this once, it should
not be possible for a loop to form (that is a < b < c and fixing b by
changing a breaks c) */
bool Change = true;
for (int Counter = 0; Counter != 10 && Change == true; Counter++)
{
Change = false;
for (pkgCache::Package **K = PList; K != PEnd; K++)
{
pkgCache::PkgIterator I(Cache,*K);
/* We attempt to install this and see if any breaks result,
this takes care of some strange cases */
if (Cache[I].CandidateVer != Cache[I].InstallVer &&
I->CurrentVer != 0 && Cache[I].InstallVer != 0 &&
(Flags[I->ID] & PreInstalled) != 0 &&
(Flags[I->ID] & Protected) == 0)
{
if (Debug == true)
cout << " Try to Re-Instate " << I.Name() << endl;
int OldBreaks = Cache.BrokenCount();
pkgCache::Version *OldVer = Cache[I].InstallVer;
Cache.MarkInstall(I,false);
if (Cache[I].InstBroken() == true ||
OldBreaks < Cache.BrokenCount())
{
if (OldVer == 0)
Cache.MarkDelete(I);
else
Cache.MarkKeep(I);
}
else
if (Debug == true)
cout << "Re-Instated " << I.Name() << endl;
}
if (Cache[I].InstallVer == 0 || Cache[I].InstBroken() == false)
continue;
// Isolate the problem dependency
PackageKill KillList[100];
PackageKill *LEnd = KillList;
for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
{
// Compute a single dependency element (glob or)
pkgCache::DepIterator Start = D;
pkgCache::DepIterator End = D;
unsigned char State = 0;
for (bool LastOR = true; D.end() == false && LastOR == true; D++)
{
State |= Cache[D];
LastOR = (D->CompareOp & pkgOP_OR) == pkgOP_OR;
if (LastOR == true)
End = D;
}
// We only worry about critical deps.
if (End.IsCritical() != true)
continue;
// Dep is ok
if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
continue;
// Hm, the group is broken.. I have no idea how to handle this
if (Start != End)
{
cout << "Note, a broken or group was found in " << I.Name() << "." << endl;
Cache.MarkDelete(I);
break;
}
if (Debug == true)
cout << "Package " << I.Name() << " has broken dep on " << End.TargetPkg().Name() << endl;
/* Conflicts is simple, decide if we should remove this package
or the conflicted one */
pkgCache::Version **VList = End.AllTargets();
bool Done = false;
for (pkgCache::Version **V = VList; *V != 0; V++)
{
pkgCache::VerIterator Ver(Cache,*V);
pkgCache::PkgIterator Pkg = Ver.ParentPkg();
if (Debug == true)
cout << " Considering " << Pkg.Name() << ' ' << (int)Scores[Pkg->ID] <<
" as a solution to " << I.Name() << ' ' << (int)Scores[I->ID] << endl;
if (Scores[I->ID] <= Scores[Pkg->ID] ||
((Cache[End] & pkgDepCache::DepGNow) == 0 &&
End->Type != pkgDEP_Conflicts))
{
if ((Flags[I->ID] & Protected) != 0)
continue;
// See if a keep will do
Cache.MarkKeep(I);
if (Cache[I].InstBroken() == false)
{
if (Debug == true)
cout << " Holding Back " << I.Name() << " rather than change " << End.TargetPkg().Name() << endl;
}
else
{
if (BrokenFix == false || DoUpgrade(I) == false)
{
if (Debug == true)
cout << " Removing " << I.Name() << " rather than change " << End.TargetPkg().Name() << endl;
Cache.MarkDelete(I);
if (Counter > 1)
Scores[I->ID] = Scores[Pkg->ID];
}
}
Change = true;
Done = true;
break;
}
else
{
// Skip this if it is protected
if ((Flags[Pkg->ID] & Protected) != 0)
continue;
LEnd->Pkg = Pkg;
LEnd->Dep = End;
LEnd++;
if (End->Type != pkgDEP_Conflicts)
break;
}
}
// Hm, nothing can possibly satisify this dep. Nuke it.
if (VList[0] == 0 && End->Type != pkgDEP_Conflicts)
{
Cache.MarkKeep(I);
if (Cache[I].InstBroken() == false)
{
if (Debug == true)
cout << " Holding Back " << I.Name() << " because I can't find " << End.TargetPkg().Name() << endl;
}
else
{
if (Debug == true)
cout << " Removing " << I.Name() << " because I can't find " << End.TargetPkg().Name() << endl;
Cache.MarkDelete(I);
}
Change = true;
Done = true;
}
delete [] VList;
if (Done == true)
break;
}
// Apply the kill list now
if (Cache[I].InstallVer != 0)
for (PackageKill *J = KillList; J != LEnd; J++)
{
Change = true;
if ((Cache[J->Dep] & pkgDepCache::DepGNow) == 0)
{
if (J->Dep->Type == pkgDEP_Conflicts)
{
if (Debug == true)
cout << " Fixing " << I.Name() << " via remove of " << J->Pkg.Name() << endl;
Cache.MarkDelete(J->Pkg);
}
}
else
{
if (Debug == true)
cout << " Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
Cache.MarkKeep(J->Pkg);
}
if (Counter > 1)
Scores[J->Pkg->ID] = Scores[I->ID];
}
}
}
if (Debug == true)
cout << "Done" << endl;
delete [] Scores;
delete [] PList;
if (Cache.BrokenCount() != 0)
return _error->Error("Internal error, ScoredFix generated breaks.");
return true;
}
/*}}}*/

91
apt-pkg/algorithms.h

@ -0,0 +1,91 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: algorithms.h,v 1.1 1998/07/07 04:17:00 jgg Exp $
/* ######################################################################
Algorithms - A set of misc algorithms
This simulate class displays what the ordering code has done and
analyses it with a fresh new dependency cache. In this way we can
see all of the effects of an upgrade run.
pkgDistUpgrade computes an upgrade that causes as many packages as
possible to move to the newest verison.
pkgApplyStatus sets the target state based on the content of the status
field in the status file. It is important to get proper crash recovery.
##################################################################### */
/*}}}*/
// Header section: pkglib
#ifndef PKGLIB_ALGORITHMS_H
#define PKGLIB_ALGORITHMS_H
#ifdef __GNUG__
#pragma interface "pkglib/algorithms.h"
#endif
#include <pkglib/packagemanager.h>
#include <pkglib/depcache.h>
class pkgSimulate : public pkgPackageManager
{
protected:
unsigned char *Flags;
pkgDepCache Sim;
// The Actuall installation implementation
virtual bool Install(PkgIterator Pkg,string File);
virtual bool Configure(PkgIterator Pkg);
virtual bool Remove(PkgIterator Pkg);
void ShortBreaks();
public:
pkgSimulate(pkgDepCache &Cache);
};
class pkgProblemResolver
{
pkgDepCache &Cache;
typedef pkgCache::PkgIterator PkgIterator;
typedef pkgCache::VerIterator VerIterator;
typedef pkgCache::DepIterator DepIterator;
typedef pkgCache::PrvIterator PrvIterator;
typedef pkgCache::Version Version;
typedef pkgCache::Package Package;
enum Flags {Protected = (1 << 0), PreInstalled = (1 << 1),
Upgradable = (1 << 2)};
signed short *Scores;
unsigned char *Flags;
bool Debug;
// Sort stuff
static pkgProblemResolver *This;
static int ScoreSort(const void *a,const void *b);
struct PackageKill
{
PkgIterator Pkg;
DepIterator Dep;
};
void MakeScores();
bool DoUpgrade(pkgCache::PkgIterator Pkg);
public:
inline void Protect(pkgCache::PkgIterator Pkg) {Flags[Pkg->ID] |= Protected;};
bool Resolve(bool BrokenFix = false);
pkgProblemResolver(pkgDepCache &Cache);
};
bool pkgDistUpgrade(pkgDepCache &Cache);
bool pkgApplyStatus(pkgDepCache &Cache);
bool pkgFixBroken(pkgDepCache &Cache);
#endif

21
apt-pkg/cacheiterators.h

@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: cacheiterators.h,v 1.3 1998/07/05 05:33:52 jgg Exp $
// $Id: cacheiterators.h,v 1.4 1998/07/07 04:17:00 jgg Exp $
/* ######################################################################
Cache Iterators - Iterators for navigating the cache structure
@ -21,7 +21,8 @@
The DepIterator can iterate over two lists, a list of 'version depends'
or a list of 'package reverse depends'. The type is determined by the
structure passed to the constructor, which should be the structure
that has the depends pointer as a member.
that has the depends pointer as a member. The provide iterator has the
same system.
This header is not user includable, please use pkglib/pkgcache.h
@ -31,6 +32,10 @@
#ifndef PKGLIB_CACHEITERATORS_H
#define PKGLIB_CACHEITERATORS_H
#ifdef __GNUG__
#pragma interface "pkglib/cacheiterators.h"
#endif
// Package Iterator
class pkgCache::PkgIterator
{
@ -57,6 +62,7 @@ class pkgCache::PkgIterator
inline Package const &operator *() const {return *Pkg;};
inline operator Package *() {return Pkg == Owner->PkgP?0:Pkg;};
inline operator Package const *() const {return Pkg == Owner->PkgP?0:Pkg;};
inline const char *Name() const {return Pkg->Name == 0?0:Owner->StrP + Pkg->Name;};
inline const char *Section() const {return Pkg->Section == 0?0:Owner->StrP + Pkg->Section;};
inline const char *TargetDist() const {return Pkg->TargetDist == 0?0:Owner->StrP + Pkg->TargetDist;};
@ -111,13 +117,14 @@ class pkgCache::VerIterator
inline Version const &operator *() const {return *Ver;};
inline operator Version *() {return Ver == Owner.VerP?0:Ver;};
inline operator Version const *() const {return Ver == Owner.VerP?0:Ver;};
inline const char *VerStr() const {return Ver->VerStr == 0?0:Owner.StrP + Ver->VerStr;};
inline const char *Section() const {return Ver->Section == 0?0:Owner.StrP + Ver->Section;};
inline PkgIterator ParentPkg() const {return PkgIterator(Owner,Owner.PkgP + Ver->ParentPkg);};
inline DepIterator DependsList() const;
inline PrvIterator ProvidesList() const;
inline unsigned long Index() const {return Ver - Owner.VerP;};
inline VerFileIterator FileList() const;
inline unsigned long Index() const {return Ver - Owner.VerP;};
inline VerIterator(pkgCache &Owner,Version *Trg = 0) : Ver(Trg), Owner(Owner)
{
@ -154,16 +161,17 @@ class pkgCache::DepIterator
inline Dependency const &operator *() const {return *Dep;};
inline operator Dependency *() {return Dep == Owner->DepP?0:Dep;};
inline operator Dependency const *() const {return Dep == Owner->DepP?0:Dep;};
inline const char *TargetVer() const {return Dep->Version == 0?0:Owner->StrP + Dep->Version;};
inline PkgIterator TargetPkg() {return PkgIterator(*Owner,Owner->PkgP + Dep->Package);};
Version **AllTargets();
bool SmartTargetPkg(PkgIterator &Result);
inline PkgIterator SmartTargetPkg() {PkgIterator R(*Owner);SmartTargetPkg(R);return R;};
inline VerIterator ParentVer() {return VerIterator(*Owner,Owner->VerP + Dep->ParentVer);};
inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[Dep->ParentVer].ParentPkg);};
bool IsCritical();
inline bool Reverse() {return Type == DepRev;};
inline unsigned long Index() const {return Dep - Owner->DepP;};
bool IsCritical();
Version **AllTargets();
bool SmartTargetPkg(PkgIterator &Result);
inline DepIterator(pkgCache &Owner,Dependency *Trg,Version * = 0) :
Dep(Trg), Type(DepVer), Owner(&Owner)
@ -208,6 +216,7 @@ class pkgCache::PrvIterator
inline Provides const &operator *() const {return *Prv;};
inline operator Provides *() {return Prv == Owner->ProvideP?0:Prv;};
inline operator Provides const *() const {return Prv == Owner->ProvideP?0:Prv;};
inline const char *Name() const {return Owner->StrP + Owner->PkgP[Prv->ParentPkg].Name;};
inline const char *ProvideVersion() const {return Prv->ProvideVersion == 0?0:Owner->StrP + Prv->ProvideVersion;};
inline PkgIterator ParentPkg() {return PkgIterator(*Owner,Owner->PkgP + Prv->ParentPkg);};

137
apt-pkg/contrib/configuration.cc

@ -0,0 +1,137 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: configuration.cc,v 1.1 1998/07/07 04:17:10 jgg Exp $
/* ######################################################################
Configuration Class
This class provides a configuration file and command line parser
for a tree-oriented configuration environment. All runtime configuration
is stored in here.
##################################################################### */
/*}}}*/
// Include files /*{{{*/
#ifdef __GNUG__
#pragma implementation "pkglib/configuration.h"
#endif
#include <pkglib/configuration.h>
#include <strutl.h>
#include <stdio.h>
/*}}}*/
Configuration *_config;
// Configuration::Configuration - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
Configuration::Configuration()
{
Root = new Item;
}
/*}}}*/
// Configuration::Lookup - Lookup a single item /*{{{*/
// ---------------------------------------------------------------------
/* This will lookup a single item by name below another item. It is a
helper function for the main lookup function */
Configuration::Item *Configuration::Lookup(Item *Head,const char *S,
unsigned long Len,bool Create)
{
int Res = 1;
Item *I = Head->Child;
Item **Last = &Head->Child;
for (; I != 0; Last = &I->Next, I = I->Next)
if ((Res = stringcasecmp(I->Value.begin(),I->Value.end(),S,S + Len)) == 0)
break;
if (Res == 0)
return I;
if (Create == false)
return 0;
I = new Item;
I->Value = string(S,Len);
I->Next = *Last;
*Last = I;
return I;
}
/*}}}*/
// Configuration::Lookup - Lookup a fully scoped item /*{{{*/
// ---------------------------------------------------------------------
/* This performs a fully scoped lookup of a given name, possibly creating
new items */
Configuration::Item *Configuration::Lookup(const char *Name,bool Create)
{
const char *Start = Name;
const char *End = Start + strlen(Name);
const char *TagEnd = Name;
Item *Itm = Root;
for (; End - TagEnd > 2; TagEnd++)
{
if (TagEnd[0] == ':' && TagEnd[1] == ':')
{
Itm = Lookup(Itm,Start,TagEnd - Start,Create);
if (Itm == 0)
return 0;
TagEnd = Start = TagEnd + 2;
}
}
Itm = Lookup(Itm,Start,End - Start,Create);
if (Itm == 0)
return 0;
return Itm;
}
/*}}}*/
// Configuration::Find - Find a value /*{{{*/
// ---------------------------------------------------------------------
/* */
string Configuration::Find(const char *Name,const char *Default)
{
Item *Itm = Lookup(Name,false);
if (Itm == 0 || Itm->Value.empty() == true)
return Default;
return Itm->Value;
}
/*}}}*/
// Configuration::FindI - Find an integer value /*{{{*/
// ---------------------------------------------------------------------
/* */
int Configuration::FindI(const char *Name,int Default)
{
Item *Itm = Lookup(Name,false);
if (Itm == 0 || Itm->Value.empty() == true)
return Default;
char *End;
int Res = strtol(Itm->Value.c_str(),&End,0);
if (End == Itm->Value.c_str())
return Default;
return Res;
}
/*}}}*/
// Configuration::Set - Set a value /*{{{*/
// ---------------------------------------------------------------------
/* */
void Configuration::Set(const char *Name,string Value)
{
Item *Itm = Lookup(Name,true);
if (Itm == 0)
return;
Itm->Value = Value;
}
/*}}}*/
// Configuration::Set - Set an integer value /*{{{*/
// ---------------------------------------------------------------------
/* */
void Configuration::Set(const char *Name,int Value)
{
Item *Itm = Lookup(Name,true);
if (Itm == 0)
return;
char S[300];
snprintf(S,sizeof(S),"%i",Value);
Itm->Value = S;
}
/*}}}*/

61
apt-pkg/contrib/configuration.h

@ -0,0 +1,61 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: configuration.h,v 1.1 1998/07/07 04:17:10 jgg Exp $
/* ######################################################################
Configuration Class
This class provides a configuration file and command line parser
for a tree-oriented configuration environment. All runtime configuration
is stored in here.
Each configuration name is given as a fully scoped string such as
Foo::Bar
And has associated with it a text string. The Configuration class only
provides storage and lookup for this tree, other classes provide
configuration file formats (and parsers/emitters if needed).
Most things can get by quite happily with,
cout << _config->Find("Foo::Bar") << endl;
##################################################################### */
/*}}}*/
// Header section: pkglib
#ifndef PKGLIB_TAGFILE_H
#define PKGLIB_TAGFILE_H
#ifdef __GNUG__
#pragma interface "pkglib/configuration.h"
#endif
#include <string>
class Configuration
{
struct Item
{
string Value;
string Tag;
Item *Child;
Item *Next;
Item() : Child(0), Next(0) {};
};
Item *Root;
Item *Lookup(Item *Head,const char *S,unsigned long Len,bool Create);
Item *Lookup(const char *Name,bool Create);
public:
string Find(const char *Name,const char *Default = 0);
int FindI(const char *Name,int Default = 0);
void Set(const char *Name,string Value);
void Set(const char *Name,int Value);
Configuration();
};
extern Configuration *_config;
#endif

74
apt-pkg/contrib/error.cc

@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: error.cc,v 1.1 1998/07/02 02:58:13 jgg Exp $
// $Id: error.cc,v 1.2 1998/07/07 04:17:10 jgg Exp $
/* ######################################################################
Global Erorr Class - Global error mechanism
@ -14,6 +14,10 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
#ifdef __GNUG__
#pragma implementation "pkglib/error.h"
#endif
#include <errno.h>
#include <stdio.h>
#include <string.h>
@ -27,7 +31,7 @@ GlobalError *_error = new GlobalError;
// GlobalError::GlobalError - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
GlobalError::GlobalError() : PendingFlag(false)
GlobalError::GlobalError() : List(0), PendingFlag(false)
{
}
/*}}}*/
@ -49,10 +53,10 @@ bool GlobalError::Errno(const char *Function,const char *Description,...)
sprintf(S + strlen(S)," - %s (%i %s)",Function,errno,strerror(errno));
// Put it on the list
Item Itm;
Itm.Text = S;
Itm.Error = true;
List.push_back(Itm);
Item *Itm = new Item;
Itm->Text = S;
Itm->Error = true;
Insert(Itm);
PendingFlag = true;
@ -72,10 +76,10 @@ bool GlobalError::Error(const char *Description,...)
vsprintf(S,Description,args);
// Put it on the list
Item Itm;
Itm.Text = S;
Itm.Error = true;
List.push_back(Itm);
Item *Itm = new Item;
Itm->Text = S;
Itm->Error = true;
Insert(Itm);
PendingFlag = true;
@ -95,10 +99,10 @@ bool GlobalError::Warning(const char *Description,...)
vsprintf(S,Description,args);
// Put it on the list
Item Itm;
Itm.Text = S;
Itm.Error = false;
List.push_back(Itm);
Item *Itm = new Item;
Itm->Text = S;
Itm->Error = false;
Insert(Itm);
return false;
}
@ -109,12 +113,17 @@ bool GlobalError::Warning(const char *Description,...)
true if the message is an error. */
bool GlobalError::PopMessage(string &Text)
{
bool Ret = List.front().Error;
Text = List.front().Text;
List.erase(List.begin());
if (List == 0)
return false;
bool Ret = List->Error;
Text = List->Text;
Item *Old = List;
List = List->Next;
delete Old;
// This really should check the list to see if only warnings are left..
if (empty())
if (List == 0)
PendingFlag = false;
return Ret;
@ -137,3 +146,30 @@ void GlobalError::DumpErrors()
}
}
/*}}}*/
// GlobalError::Discard - Discard /*{{{*/
// ---------------------------------------------------------------------
/* */
void GlobalError::Discard()
{
while (List != 0)
{
Item *Old = List;
List = List->Next;
delete Old;
}
PendingFlag = false;
};
/*}}}*/
// GlobalError::Insert - Insert a new item at the end /*{{{*/
// ---------------------------------------------------------------------
/* */
void GlobalError::Insert(Item *Itm)
{
Item **End = &List;
for (Item *I = List; I != 0; I = I->Next)
End = &I->Next;
Itm->Next = *End;
*End = Itm;
}
/*}}}*/

15
apt-pkg/contrib/error.h

@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: error.h,v 1.1 1998/07/02 02:58:13 jgg Exp $
// $Id: error.h,v 1.2 1998/07/07 04:17:11 jgg Exp $
/* ######################################################################
Global Erorr Class - Global error mechanism
@ -41,8 +41,11 @@
#ifndef PKGLIB_ERROR_H
#define PKGLIB_ERROR_H
#ifdef __GNUG__
#pragma interface "pkglib/error.h"
#endif
#include <string>
#include <vector.h>
class GlobalError
{
@ -50,10 +53,12 @@ class GlobalError
{
string Text;
bool Error;
Item *Next;
};
vector<Item> List;
Item *List;
bool PendingFlag;
void Insert(Item *I);
public:
@ -67,9 +72,9 @@ class GlobalError
// Simple accessors
inline bool PendingError() {return PendingFlag;};
inline bool empty() {return List.empty();};
inline bool empty() {return List == 0;};
bool PopMessage(string &Text);
void Discard() {List.erase(List.begin(),List.end()); PendingFlag = false;};
void Discard();
// Usefull routine to dump to cerr
void DumpErrors();

5
apt-pkg/contrib/fileutl.cc

@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: fileutl.cc,v 1.2 1998/07/04 05:57:41 jgg Exp $
// $Id: fileutl.cc,v 1.3 1998/07/07 04:17:12 jgg Exp $
/* ######################################################################
File Utilities
@ -14,6 +14,9 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
#ifdef __GNUG__
#pragma implementation "pkglib/fileutl.h"
#endif
#include <pkglib/fileutl.h>
#include <pkglib/error.h>

6
apt-pkg/contrib/fileutl.h

@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: fileutl.h,v 1.1 1998/07/02 02:58:13 jgg Exp $
// $Id: fileutl.h,v 1.2 1998/07/07 04:17:13 jgg Exp $
/* ######################################################################
File Utilities
@ -22,6 +22,10 @@
#ifndef PKGLIB_FILEUTL_H
#define PKGLIB_FILEUTL_H
#ifdef __GNUG__
#pragma interface "pkglib/fileutl.h"
#endif
#include <string>
class File

6
apt-pkg/contrib/mmap.cc

@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: mmap.cc,v 1.3 1998/07/04 22:32:15 jgg Exp $
// $Id: mmap.cc,v 1.4 1998/07/07 04:17:14 jgg Exp $
/* ######################################################################
MMap Class - Provides 'real' mmap or a faked mmap using read().
@ -21,6 +21,10 @@
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
#ifdef __GNUG__
#pragma implementation "pkglib/mmap.h"
#endif
#define _BSD_SOURCE
#include <pkglib/mmap.h>
#include <pkglib/error.h>

6
apt-pkg/contrib/mmap.h

@ -1,6 +1,6 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: mmap.h,v 1.2 1998/07/04 05:57:43 jgg Exp $
// $Id: mmap.h,v 1.3 1998/07/07 04:17:15 jgg Exp $
/* ######################################################################
MMap Class - Provides 'real' mmap or a faked mmap using read().
@ -26,6 +26,10 @@
#ifndef PKGLIB_MMAP_H
#define PKGLIB_MMAP_H
#ifdef __GNUG__
#pragma interface "pkglib/mmap.h"
#endif
#include <string>
#include <pkglib/fileutl.h>

343
apt-pkg/contrib/strutl.cc

@ -0,0 +1,343 @@
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
// $Id: strutl.cc,v 1.1 1998/07/07 04:17:16 jgg Exp $
/* ######################################################################
String Util - Some usefull string functions.
strstrip - Remove whitespace from the front and end of a line.
This source is placed in the Public Domain, do with it what you will
It was originally written by Jason Gunthorpe <jgg@gpu.srv.ualberta.ca>
##################################################################### */
/*}}}*/
// Includes /*{{{*/
#include <strutl.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
/*}}}*/
// strstrip - Remove white space from the front and back of a string /*{{{*/
// ---------------------------------------------------------------------
/* This is handy to use when parsing a file. It also removes \n's left
over from fgets and company */
char *_strstrip(char *String)
{
for (;*String != 0 && (*String == ' ' || *String == '\t'); String++);
if (*String == 0)
return String;
char *End = String + strlen(String) - 1;
for (;End != String - 1 && (*End == ' ' || *End == '\t' || *End == '\n' ||
*End == '\r'); End--);
End++;
*End = 0;
return String;
};
/*}}}*/
// strtabexpand - Converts tabs into 8 spaces /*{{{*/
// ---------------------------------------------------------------------
/* */
char *_strtabexpand(char *String,size_t Len)
{
for (char *I = String; I != I + Len && *I != 0; I++)
{
if (*I != '\t')
continue;
if (I + 8 > String + Len)
{
*I = 0;
return String;
}
/* Assume the start of the string is 0 and find the next 8 char
division */
int Len;
if (String == I)
Len = 1;
else
Len = 8 - ((String - I) % 8);
Len -= 2;
if (Len <= 0)
{
*I = ' ';
continue;
}
memmove(I + Len,I + 1,strlen(I) + 1);
for (char *J = I; J + Len != I; *I = ' ', I++);
}
return String;
}
/*}}}*/
// ParseQuoteWord - Parse a single word out of a string /*{{{*/
// ---------------------------------------------------------------------
/* This grabs a single word, converts any % escaped characters to their
proper values and advances the pointer. Double quotes are understood
and striped out as well. */
bool ParseQuoteWord(const char *&String,string &Res)
{
// Skip leading whitespace
const char *C = String;
for (;*C != 0 && *C == ' '; C++);
if (*C == 0)
return false;
// Jump to the next word
for (;*C != 0 && *C != ' '; C++)
{
if (*C == '"')
{
for (C++;*C != 0 && *C != '"'; C++);
if (*C == 0)
return false;
}
}
// Now de-quote characters
char Buffer[1024];
char Tmp[3];
const char *Start = String;
char *I;
for (I = Buffer; I < Buffer + sizeof(Buffer) && Start != C; I++)
{
if (*Start == '%' && Start + 2 < C)
{
Tmp[0] = Start[1];
Tmp[1] = Start[2];
Tmp[3] = 0;
*I = (char)strtol(Tmp,0,16);
Start += 3;
continue;
}
if (*Start != '"')
*I = *Start;
else
I--;
Start++;
}