diff options
author | Arch Librarian <arch@canonical.com> | 2004-09-20 16:56:32 +0000 |
---|---|---|
committer | Arch Librarian <arch@canonical.com> | 2004-09-20 16:56:32 +0000 |
commit | b2e465d6d32d2dc884f58b94acb7e35f671a87fe (patch) | |
tree | 5928383b9bde7b0ba9812e6526ad746466e558f7 /apt-pkg/deb | |
parent | 00b47c98ca4a4349686a082eba6d77decbb03a4d (diff) |
Join with aliencode
Author: jgg
Date: 2001-02-20 07:03:16 GMT
Join with aliencode
Diffstat (limited to 'apt-pkg/deb')
-rw-r--r-- | apt-pkg/deb/debindexfile.cc | 506 | ||||
-rw-r--r-- | apt-pkg/deb/debindexfile.h | 112 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.cc | 221 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.h | 36 | ||||
-rw-r--r-- | apt-pkg/deb/debrecords.cc | 23 | ||||
-rw-r--r-- | apt-pkg/deb/debrecords.h | 12 | ||||
-rw-r--r-- | apt-pkg/deb/debsrcrecords.cc | 97 | ||||
-rw-r--r-- | apt-pkg/deb/debsrcrecords.h | 24 | ||||
-rw-r--r-- | apt-pkg/deb/debsystem.cc | 197 | ||||
-rw-r--r-- | apt-pkg/deb/debsystem.h | 41 | ||||
-rw-r--r-- | apt-pkg/deb/debversion.cc | 266 | ||||
-rw-r--r-- | apt-pkg/deb/debversion.h | 72 | ||||
-rw-r--r-- | apt-pkg/deb/dpkginit.cc | 119 | ||||
-rw-r--r-- | apt-pkg/deb/dpkginit.h | 34 | ||||
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 162 | ||||
-rw-r--r-- | apt-pkg/deb/dpkgpm.h | 8 |
16 files changed, 1610 insertions, 320 deletions
diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc new file mode 100644 index 000000000..67afc89e6 --- /dev/null +++ b/apt-pkg/deb/debindexfile.cc @@ -0,0 +1,506 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: debindexfile.cc,v 1.2 2001/02/20 07:03:17 jgg Exp $ +/* ###################################################################### + + Debian Specific sources.list types and the three sorts of Debian + index files. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#ifdef __GNUG__ +#pragma implementation "apt-pkg/debindexfile.h" +#endif + +#include <apt-pkg/debindexfile.h> +#include <apt-pkg/debsrcrecords.h> +#include <apt-pkg/deblistparser.h> +#include <apt-pkg/debrecords.h> +#include <apt-pkg/sourcelist.h> +#include <apt-pkg/configuration.h> +#include <apt-pkg/progress.h> +#include <apt-pkg/error.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/acquire-item.h> + +#include <sys/stat.h> + /*}}}*/ + +// SourcesIndex::debSourcesIndex - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section) : + URI(URI), Dist(Dist), Section(Section) +{ +} + /*}}}*/ +// SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/ +// --------------------------------------------------------------------- +/* The result looks like: + http://foo/ stable/main src 1.1.1 (dsc) */ +string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, + pkgSrcRecords::File const &File) const +{ + string Res; + Res = ::URI::SiteOnly(URI) + ' '; + if (Dist[Dist.size() - 1] == '/') + { + if (Dist != "/") + Res += Dist; + } + else + Res += Dist + '/' + Section; + + Res += " "; + Res += Record.Package(); + Res += " "; + Res += Record.Version(); + if (File.Type.empty() == false) + Res += " (" + File.Type + ")"; + return Res; +} + /*}}}*/ +// SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const +{ + string SourcesURI; + if (Dist[Dist.size() - 1] == '/') + SourcesURI = URI + Dist; + else + SourcesURI = URI + "dists/" + Dist + '/' + Section + + "/source/"; + + SourcesURI += "Sources"; + SourcesURI = URItoFileName(SourcesURI); + return new debSrcRecordParser(_config->FindDir("Dir::State::lists") + + SourcesURI,this); +} + /*}}}*/ +// SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/ +// --------------------------------------------------------------------- +/* */ +string debSourcesIndex::Describe() const +{ + char S[300]; + snprintf(S,sizeof(S),"%s (%s)",Info("Packages").c_str(), + IndexFile("Sources").c_str()); + return S; +} + /*}}}*/ +// SourcesIndex::Info - One liner describing the index URI /*{{{*/ +// --------------------------------------------------------------------- +/* */ +string debSourcesIndex::Info(const char *Type) const +{ + string Info = ::URI::SiteOnly(URI) + ' '; + if (Dist[Dist.size() - 1] == '/') + { + if (Dist != "/") + Info += Dist; + } + else + Info += Dist + '/' + Section; + Info += " "; + Info += Type; + return Info; +} + /*}}}*/ +// SourcesIndex::Index* - Return the URI to the index files /*{{{*/ +// --------------------------------------------------------------------- +/* */ +inline string debSourcesIndex::IndexFile(const char *Type) const +{ + return URItoFileName(IndexURI(Type)); +} +string debSourcesIndex::IndexURI(const char *Type) const +{ + string Res; + if (Dist[Dist.size() - 1] == '/') + { + if (Dist != "/") + Res = URI + Dist; + else + Res = URI; + } + else + Res = URI + "dists/" + Dist + '/' + Section + + "/source/"; + + Res += Type; + return Res; +} + /*}}}*/ +// SourcesIndex::GetIndexes - Fetch the index files /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debSourcesIndex::GetIndexes(pkgAcquire *Owner) const +{ + new pkgAcqIndex(Owner,IndexURI("Sources"),Info("Sources"),"Sources"); + new pkgAcqIndexRel(Owner,IndexURI("Release"),Info("Release"),"Release"); + return true; +} + /*}}}*/ +// SourcesIndex::Exists - Check if the index is available /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debSourcesIndex::Exists() const +{ + return FileExists(IndexFile("Sources")); +} + /*}}}*/ +// SourcesIndex::Size - Return the size of the index /*{{{*/ +// --------------------------------------------------------------------- +/* */ +unsigned long debSourcesIndex::Size() const +{ + struct stat S; + if (stat(IndexFile("Sources").c_str(),&S) != 0) + return 0; + return S.st_size; +} + /*}}}*/ + +// PackagesIndex::debPackagesIndex - Contructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +debPackagesIndex::debPackagesIndex(string URI,string Dist,string Section) : + URI(URI), Dist(Dist), Section(Section) +{ +} + /*}}}*/ +// PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/ +// --------------------------------------------------------------------- +/* This is a shorter version that is designed to be < 60 chars or so */ +string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const +{ + string Res = ::URI::SiteOnly(URI) + ' '; + if (Dist[Dist.size() - 1] == '/') + { + if (Dist != "/") + Res += Dist; + } + else + Res += Dist + '/' + Section; + + Res += " "; + Res += Ver.ParentPkg().Name(); + Res += " "; + Res += Ver.VerStr(); + return Res; +} + /*}}}*/ +// PackagesIndex::Describe - Give a descriptive path to the index /*{{{*/ +// --------------------------------------------------------------------- +/* This should help the user find the index in the sources.list and + in the filesystem for problem solving */ +string debPackagesIndex::Describe() const +{ + char S[300]; + snprintf(S,sizeof(S),"%s (%s)",Info("Packages").c_str(), + IndexFile("Packages").c_str()); + return S; +} + /*}}}*/ +// PackagesIndex::Info - One liner describing the index URI /*{{{*/ +// --------------------------------------------------------------------- +/* */ +string debPackagesIndex::Info(const char *Type) const +{ + string Info = ::URI::SiteOnly(URI) + ' '; + if (Dist[Dist.size() - 1] == '/') + { + if (Dist != "/") + Info += Dist; + } + else + Info += Dist + '/' + Section; + Info += " "; + Info += Type; + return Info; +} + /*}}}*/ +// PackagesIndex::Index* - Return the URI to the index files /*{{{*/ +// --------------------------------------------------------------------- +/* */ +inline string debPackagesIndex::IndexFile(const char *Type) const +{ + return _config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type)); +} +string debPackagesIndex::IndexURI(const char *Type) const +{ + string Res; + if (Dist[Dist.size() - 1] == '/') + { + if (Dist != "/") + Res = URI + Dist; + else + Res = URI; + } + else + Res = URI + "dists/" + Dist + '/' + Section + + "/binary-" + _config->Find("APT::Architecture") + '/'; + + Res += Type; + return Res; +} + /*}}}*/ +// PackagesIndex::GetIndexes - Fetch the index files /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debPackagesIndex::GetIndexes(pkgAcquire *Owner) const +{ + new pkgAcqIndex(Owner,IndexURI("Packages"),Info("Packages"),"Packages"); + new pkgAcqIndexRel(Owner,IndexURI("Release"),Info("Release"),"Release"); + return true; +} + /*}}}*/ +// PackagesIndex::Exists - Check if the index is available /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debPackagesIndex::Exists() const +{ + return FileExists(IndexFile("Packages")); +} + /*}}}*/ +// PackagesIndex::Size - Return the size of the index /*{{{*/ +// --------------------------------------------------------------------- +/* This is really only used for progress reporting. */ +unsigned long debPackagesIndex::Size() const +{ + struct stat S; + if (stat(IndexFile("Packages").c_str(),&S) != 0) + return 0; + return S.st_size; +} + /*}}}*/ +// PackagesIndex::Merge - Load the index file into a cache /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const +{ + string PackageFile = IndexFile("Packages"); + FileFd Pkg(PackageFile,FileFd::ReadOnly); + debListParser Parser(&Pkg); + if (_error->PendingError() == true) + return _error->Error("Problem opening %s",PackageFile.c_str()); + + Prog.SubProgress(0,Info("Packages")); + ::URI Tmp(URI); + if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false) + return _error->Error("Problem with SelectFile %s",PackageFile.c_str()); + + // Store the IMS information + pkgCache::PkgFileIterator File = Gen.GetCurFile(); + struct stat St; + if (fstat(Pkg.Fd(),&St) != 0) + return _error->Errno("fstat","Failed to stat"); + File->Size = St.st_size; + File->mtime = St.st_mtime; + + if (Gen.MergeList(Parser) == false) + return _error->Error("Problem with MergeList %s",PackageFile.c_str()); + + // Check the release file + string ReleaseFile = IndexFile("Release"); + if (FileExists(ReleaseFile) == true) + { + FileFd Rel(ReleaseFile,FileFd::ReadOnly); + if (_error->PendingError() == true) + return false; + Parser.LoadReleaseInfo(File,Rel); + } + + return true; +} + /*}}}*/ +// PackagesIndex::FindInCache - Find this index /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const +{ + string FileName = IndexFile("Packages"); + pkgCache::PkgFileIterator File = Cache.FileBegin(); + for (; File.end() == false; File++) + { + if (FileName != File.FileName()) + continue; + + struct stat St; + if (stat(File.FileName(),&St) != 0) + return pkgCache::PkgFileIterator(Cache); + if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) + return pkgCache::PkgFileIterator(Cache); + return File; + } + + return File; +} + /*}}}*/ + +// StatusIndex::debStatusIndex - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +debStatusIndex::debStatusIndex(string File) : File(File) +{ +} + /*}}}*/ +// StatusIndex::Size - Return the size of the index /*{{{*/ +// --------------------------------------------------------------------- +/* */ +unsigned long debStatusIndex::Size() const +{ + struct stat S; + if (stat(File.c_str(),&S) != 0) + return 0; + return S.st_size; +} + /*}}}*/ +// StatusIndex::Merge - Load the index file into a cache /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const +{ + FileFd Pkg(File,FileFd::ReadOnly); + if (_error->PendingError() == true) + return false; + debListParser Parser(&Pkg); + if (_error->PendingError() == true) + return false; + + Prog.SubProgress(0,File); + if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false) + return _error->Error("Problem with SelectFile %s",File.c_str()); + + // Store the IMS information + pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); + struct stat St; + if (fstat(Pkg.Fd(),&St) != 0) + return _error->Errno("fstat","Failed to stat"); + CFile->Size = St.st_size; + CFile->mtime = St.st_mtime; + CFile->Archive = Gen.WriteUniqString("now"); + + if (Gen.MergeList(Parser) == false) + return _error->Error("Problem with MergeList %s",File.c_str()); + return true; +} + /*}}}*/ +// StatusIndex::FindInCache - Find this index /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const +{ + pkgCache::PkgFileIterator File = Cache.FileBegin(); + for (; File.end() == false; File++) + { + if (this->File != File.FileName()) + continue; + + struct stat St; + if (stat(File.FileName(),&St) != 0) + return pkgCache::PkgFileIterator(Cache); + if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) + return pkgCache::PkgFileIterator(Cache); + return File; + } + return File; +} + /*}}}*/ +// StatusIndex::Exists - Check if the index is available /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debStatusIndex::Exists() const +{ + // Abort if the file does not exist. + return true; +} + /*}}}*/ + +// Source List types for Debian /*{{{*/ +class debSLTypeDeb : public pkgSourceList::Type +{ + public: + + bool CreateItem(vector<pkgIndexFile *> &List,string URI, + string Dist,string Section) const + { + List.push_back(new debPackagesIndex(URI,Dist,Section)); + return true; + }; + + debSLTypeDeb() + { + Name = "deb"; + Label = "Standard Debian binary tree"; + } +}; + +class debSLTypeDebSrc : public pkgSourceList::Type +{ + public: + + bool CreateItem(vector<pkgIndexFile *> &List,string URI, + string Dist,string Section) const + { + List.push_back(new debSourcesIndex(URI,Dist,Section)); + return true; + }; + + debSLTypeDebSrc() + { + Name = "deb-src"; + Label = "Standard Debian source tree"; + } +}; + +debSLTypeDeb _apt_DebType; +debSLTypeDebSrc _apt_DebSrcType; + /*}}}*/ +// Index File types for Debian /*{{{*/ +class debIFTypeSrc : public pkgIndexFile::Type +{ + public: + + debIFTypeSrc() {Label = "Debian Source Index";}; +}; +class debIFTypePkg : public pkgIndexFile::Type +{ + public: + + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + { + return new debRecordParser(File.FileName(),*File.Cache()); + }; + debIFTypePkg() {Label = "Debian Package Index";}; +}; +class debIFTypeStatus : public pkgIndexFile::Type +{ + public: + + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + { + return new debRecordParser(File.FileName(),*File.Cache()); + }; + debIFTypeStatus() {Label = "Debian dpkg status file";}; +}; +static debIFTypeSrc _apt_Src; +static debIFTypePkg _apt_Pkg; +static debIFTypeStatus _apt_Status; + +const pkgIndexFile::Type *debSourcesIndex::GetType() const +{ + return &_apt_Src; +} +const pkgIndexFile::Type *debPackagesIndex::GetType() const +{ + return &_apt_Pkg; +} +const pkgIndexFile::Type *debStatusIndex::GetType() const +{ + return &_apt_Status; +} + + /*}}}*/ diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h new file mode 100644 index 000000000..b4dee3c22 --- /dev/null +++ b/apt-pkg/deb/debindexfile.h @@ -0,0 +1,112 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: debindexfile.h,v 1.2 2001/02/20 07:03:17 jgg Exp $ +/* ###################################################################### + + Debian Index Files + + There are three sorts currently + + Package files that have File: tags + Package files that don't (/var/lib/dpkg/status) + Source files + + ##################################################################### */ + /*}}}*/ +#ifndef PKGLIB_DEBINDEXFILE_H +#define PKGLIB_DEBINDEXFILE_H + +#ifdef __GNUG__ +#pragma interface "apt-pkg/debindexfile.h" +#endif + +#include <apt-pkg/indexfile.h> + +class debStatusIndex : public pkgIndexFile +{ + string File; + + public: + + virtual const Type *GetType() const; + + // Interface for acquire + virtual string Describe() const {return File;}; + + // Interface for the Cache Generator + virtual bool Exists() const; + virtual bool HasPackages() const {return true;}; + virtual unsigned long Size() const; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const; + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + + debStatusIndex(string File); +}; + +class debPackagesIndex : public pkgIndexFile +{ + string URI; + string Dist; + string Section; + + string Info(const char *Type) const; + string IndexFile(const char *Type) const; + string IndexURI(const char *Type) const; + + public: + + virtual const Type *GetType() const; + + // Stuff for accessing files on remote items + virtual string ArchiveInfo(pkgCache::VerIterator Ver) const; + virtual string ArchiveURI(string File) const {return URI + File;}; + + // Interface for acquire + virtual string Describe() const; + virtual bool GetIndexes(pkgAcquire *Owner) const; + + // Interface for the Cache Generator + virtual bool Exists() const; + virtual bool HasPackages() const {return true;}; + virtual unsigned long Size() const; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const; + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + + debPackagesIndex(string URI,string Dist,string Section); +}; + +class debSourcesIndex : public pkgIndexFile +{ + string URI; + string Dist; + string Section; + + string Info(const char *Type) const; + string IndexFile(const char *Type) const; + string IndexURI(const char *Type) const; + + public: + + virtual const Type *GetType() const; + + // Stuff for accessing files on remote items + virtual string SourceInfo(pkgSrcRecords::Parser const &Record, + pkgSrcRecords::File const &File) const; + virtual string ArchiveURI(string File) const {return URI + File;}; + + // Interface for acquire + virtual string Describe() const; + virtual bool GetIndexes(pkgAcquire *Owner) const; + + // Interface for the record parsers + virtual pkgSrcRecords::Parser *CreateSrcParser() const; + + // Interface for the Cache Generator + virtual bool Exists() const; + virtual bool HasPackages() const {return false;}; + virtual unsigned long Size() const; + + debSourcesIndex(string URI,string Dist,string Section); +}; + +#endif diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 9da03a7f6..2b3dfaf6e 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: deblistparser.cc,v 1.23 1999/09/30 06:30:34 jgg Exp $ +// $Id: deblistparser.cc,v 1.24 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### Package Cache Generator - Generator for the cache structure. @@ -19,10 +19,17 @@ #include <system.h> /*}}}*/ +static debListParser::WordList PrioList[] = {{"important",pkgCache::State::Important}, + {"required",pkgCache::State::Required}, + {"standard",pkgCache::State::Standard}, + {"optional",pkgCache::State::Optional}, + {"extra",pkgCache::State::Extra}, + {}}; + // ListParser::debListParser - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -debListParser::debListParser(FileFd &File) : Tags(File) +debListParser::debListParser(FileFd *File) : Tags(File) { Arch = _config->Find("APT::architecture"); } @@ -80,14 +87,8 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) const char *Start; const char *Stop; if (Section.Find("Priority",Start,Stop) == true) - { - WordList PrioList[] = {{"important",pkgCache::State::Important}, - {"required",pkgCache::State::Required}, - {"standard",pkgCache::State::Standard}, - {"optional",pkgCache::State::Optional}, - {"extra",pkgCache::State::Extra}}; - if (GrabWord(string(Start,Stop-Start),PrioList, - _count(PrioList),Ver->Priority) == false) + { + if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false) Ver->Priority = pkgCache::State::Extra; } @@ -104,6 +105,10 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false) return false; + // Obsolete. + if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false) + return false; + if (ParseProvides(Ver) == false) return false; @@ -205,9 +210,9 @@ bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg, {"install",pkgCache::State::Install}, {"hold",pkgCache::State::Hold}, {"deinstall",pkgCache::State::DeInstall}, - {"purge",pkgCache::State::Purge}}; - if (GrabWord(string(Start,I-Start),WantList, - _count(WantList),Pkg->SelectedState) == false) + {"purge",pkgCache::State::Purge}, + {}}; + if (GrabWord(string(Start,I-Start),WantList,Pkg->SelectedState) == false) return _error->Error("Malformed 1st word in the Status line"); // Isloate the next word @@ -221,9 +226,9 @@ bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg, WordList FlagList[] = {{"ok",pkgCache::State::Ok}, {"reinstreq",pkgCache::State::ReInstReq}, {"hold",pkgCache::State::HoldInst}, - {"hold-reinstreq",pkgCache::State::HoldReInstReq}}; - if (GrabWord(string(Start,I-Start),FlagList, - _count(FlagList),Pkg->InstState) == false) + {"hold-reinstreq",pkgCache::State::HoldReInstReq}, + {}}; + if (GrabWord(string(Start,I-Start),FlagList,Pkg->InstState) == false) return _error->Error("Malformed 2nd word in the Status line"); // Isloate the last word @@ -241,9 +246,9 @@ bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg, {"half-installed",pkgCache::State::HalfInstalled}, {"config-files",pkgCache::State::ConfigFiles}, {"post-inst-failed",pkgCache::State::HalfConfigured}, - {"removal-failed",pkgCache::State::HalfInstalled}}; - if (GrabWord(string(Start,I-Start),StatusList, - _count(StatusList),Pkg->CurrentState) == false) + {"removal-failed",pkgCache::State::HalfInstalled}, + {}}; + if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false) return _error->Error("Malformed 3rd word in the Status line"); /* A Status line marks the package as indicating the current @@ -266,9 +271,67 @@ bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg, // --------------------------------------------------------------------- /* This parses the dependency elements out of a standard string in place, bit by bit. */ +const char *debListParser::ConvertRelation(const char *I,unsigned int &Op) +{ + // Determine the operator + switch (*I) + { + case '<': + I++; + if (*I == '=') + { + I++; + Op = pkgCache::Dep::LessEq; + break; + } + + if (*I == '<') + { + I++; + Op = pkgCache::Dep::Less; + break; + } + + // < is the same as <= and << is really Cs < for some reason + Op = pkgCache::Dep::LessEq; + break; + + case '>': + I++; + if (*I == '=') + { + I++; + Op = pkgCache::Dep::GreaterEq; + break; + } + + if (*I == '>') + { + I++; + Op = pkgCache::Dep::Greater; + break; + } + + // > is the same as >= and >> is really Cs > for some reason + Op = pkgCache::Dep::GreaterEq; + break; + + case '=': + Op = pkgCache::Dep::Equals; + I++; + break; + + // HACK around bad package definitions + default: + Op = pkgCache::Dep::Equals; + break; + } + return I; +} + const char *debListParser::ParseDepends(const char *Start,const char *Stop, string &Package,string &Ver, - unsigned int &Op) + unsigned int &Op, bool ParseArchFlags) { // Strip off leading space for (;Start != Stop && isspace(*Start) != 0; Start++); @@ -298,60 +361,7 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, for (I++; I != Stop && isspace(*I) != 0 ; I++); if (I + 3 >= Stop) return 0; - - // Determine the operator - switch (*I) - { - case '<': - I++; - if (*I == '=') - { - I++; - Op = pkgCache::Dep::LessEq; - break; - } - - if (*I == '<') - { - I++; - Op = pkgCache::Dep::Less; - break; - } - - // < is the same as <= and << is really Cs < for some reason - Op = pkgCache::Dep::LessEq; - break; - - case '>': - I++; - if (*I == '=') - { - I++; - Op = pkgCache::Dep::GreaterEq; - break; - } - - if (*I == '>') - { - I++; - Op = pkgCache::Dep::Greater; - break; - } - - // > is the same as >= and >> is really Cs > for some reason - Op = pkgCache::Dep::GreaterEq; - break; - - case '=': - Op = pkgCache::Dep::Equals; - I++; - break; - - // HACK around bad package definitions - default: - Op = pkgCache::Dep::Equals; - break; - } + I = ConvertRelation(I,Op); // Skip whitespace for (;I != Stop && isspace(*I) != 0; I++); @@ -375,6 +385,50 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, // Skip whitespace for (;I != Stop && isspace(*I) != 0; I++); + + if (ParseArchFlags == true) + { + string arch = _config->Find("APT::Architecture"); + + // Parse an architecture + if (I != Stop && *I == '[') + { + // malformed + I++; + if (I == Stop) + return 0; + + const char *End = I; + bool Found = false; + while (I != Stop) + { + // look for whitespace or ending ']' + while (End != Stop && !isspace(*End) && *End != ']') + End++; + + if (End == Stop) + return 0; + + if (stringcmp(I,End,arch.begin(),arch.end()) == 0) + Found = true; + + if (*End++ == ']') { + I = End; + break; + } + + I = End; + for (;I != Stop && isspace(*I) != 0; I++); + } + + if (Found == false) + Package = ""; /* not for this arch */ + } + + // Skip whitespace + for (;I != Stop && isspace(*I) != 0; I++); + } + if (I != Stop && *I == '|') Op |= pkgCache::Dep::Or; @@ -453,10 +507,9 @@ bool debListParser::ParseProvides(pkgCache::VerIterator Ver) // ListParser::GrabWord - Matches a word and returns /*{{{*/ // --------------------------------------------------------------------- /* Looks for a word in a list of words - for ParseStatus */ -bool debListParser::GrabWord(string Word,WordList *List,int Count, - unsigned char &Out) +bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out) { - for (int C = 0; C != Count; C++) + for (unsigned int C = 0; List[C].Str != 0; C++) { if (strcasecmp(Word.c_str(),List[C].Str) == 0) { @@ -500,7 +553,7 @@ bool debListParser::Step() bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI, FileFd &File) { - pkgTagFile Tags(File); + pkgTagFile Tags(&File); pkgTagSection Section; if (Tags.Step(Section) == false) return false; @@ -527,3 +580,15 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI, return !_error->PendingError(); } /*}}}*/ +// ListParser::GetPrio - Convert the priority from a string /*{{{*/ +// --------------------------------------------------------------------- +/* */ +unsigned char debListParser::GetPrio(string Str) +{ + unsigned char Out; + if (GrabWord(Str,PrioList,Out) == false) + Out = pkgCache::State::Extra; + + return Out; +} + /*}}}*/ diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 6e2c5ef94..9f305211a 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: deblistparser.h,v 1.8 1999/07/26 17:46:08 jgg Exp $ +// $Id: deblistparser.h,v 1.9 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### Debian Package List Parser - This implements the abstract parser @@ -8,7 +8,6 @@ ##################################################################### */ /*}}}*/ -// Header section: pkglib #ifndef PKGLIB_DEBLISTPARSER_H #define PKGLIB_DEBLISTPARSER_H @@ -17,29 +16,33 @@ class debListParser : public pkgCacheGenerator::ListParser { - pkgTagFile Tags; - pkgTagSection Section; - unsigned long iOffset; - string Arch; - + public: + // Parser Helper struct WordList { - char *Str; + const char *Str; unsigned char Val; }; + private: + + pkgTagFile Tags; + pkgTagSection Section; + unsigned long iOffset; + string Arch; + unsigned long UniqFindTagWrite(const char *Tag); bool ParseStatus(pkgCache::PkgIterator Pkg,pkgCache::VerIterator Ver); - const char *ParseDepends(const char *Start,const char *Stop, - string &Package,string &Ver,unsigned int &Op); bool ParseDepends(pkgCache::VerIterator Ver,const char *Tag, unsigned int Type); bool ParseProvides(pkgCache::VerIterator Ver); - bool GrabWord(string Word,WordList *List,int Count,unsigned char &Out); + static bool GrabWord(string Word,WordList *List,unsigned char &Out); public: - + + static unsigned char GetPrio(string Str); + // These all operate against the current section virtual string Package(); virtual string Version(); @@ -51,10 +54,15 @@ class debListParser : public pkgCacheGenerator::ListParser virtual unsigned long Size() {return Section.size();}; virtual bool Step(); - + bool LoadReleaseInfo(pkgCache::PkgFileIterator FileI,FileFd &File); - debListParser(FileFd &File); + static const char *ParseDepends(const char *Start,const char *Stop, + string &Package,string &Ver,unsigned int &Op, + bool ParseArchFlags = false); + static const char *ConvertRelation(const char *I,unsigned int &Op); + + debListParser(FileFd *File); }; #endif diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index 49e3d02c8..0196992c6 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/apt-pkg/deb/debrecords.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: debrecords.cc,v 1.8 1999/05/18 05:28:03 jgg Exp $ +// $Id: debrecords.cc,v 1.9 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### Debian Package Records - Parser for debian package records @@ -18,8 +18,9 @@ // RecordParser::debRecordParser - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -debRecordParser::debRecordParser(FileFd &File,pkgCache &Cache) : - Tags(File,Cache.Head().MaxVerFileSize + 20) +debRecordParser::debRecordParser(string FileName,pkgCache &Cache) : + File(FileName,FileFd::ReadOnly), + Tags(&File,Cache.Head().MaxVerFileSize + 200) { } /*}}}*/ @@ -39,6 +40,14 @@ string debRecordParser::FileName() return Section.FindS("Filename"); } /*}}}*/ +// RecordParser::Name - Return the package name /*{{{*/ +// --------------------------------------------------------------------- +/* */ +string debRecordParser::Name() +{ + return Section.FindS("Package"); +} + /*}}}*/ // RecordParser::MD5Hash - Return the archive hash /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -87,3 +96,11 @@ string debRecordParser::SourcePkg() return string(Res,0,Pos); } /*}}}*/ +// RecordParser::GetRec - Return the whole record /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void debRecordParser::GetRec(const char *&Start,const char *&Stop) +{ + Section.GetSection(Start,Stop); +} + /*}}}*/ diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h index 9191ebcda..fd1c380dc 100644 --- a/apt-pkg/deb/debrecords.h +++ b/apt-pkg/deb/debrecords.h @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: debrecords.h,v 1.6 1999/04/07 05:30:18 jgg Exp $ +// $Id: debrecords.h,v 1.7 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### Debian Package Records - Parser for debian package records @@ -11,7 +11,6 @@ ##################################################################### */ /*}}}*/ -// Header section: pkglib #ifndef PKGLIB_DEBRECORDS_H #define PKGLIB_DEBRECORDS_H @@ -24,9 +23,10 @@ class debRecordParser : public pkgRecords::Parser { + FileFd File; pkgTagFile Tags; pkgTagSection Section; - + protected: virtual bool Jump(pkgCache::VerFileIterator const &Ver); @@ -42,9 +42,11 @@ class debRecordParser : public pkgRecords::Parser virtual string Maintainer(); virtual string ShortDesc(); virtual string LongDesc(); + virtual string Name(); + + virtual void GetRec(const char *&Start,const char *&Stop); - debRecordParser(FileFd &File,pkgCache &Cache); + debRecordParser(string FileName,pkgCache &Cache); }; - #endif diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc index 7a06e30b9..d452095cd 100644 --- a/apt-pkg/deb/debsrcrecords.cc +++ b/apt-pkg/deb/debsrcrecords.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: debsrcrecords.cc,v 1.3 1999/04/07 05:30:18 jgg Exp $ +// $Id: debsrcrecords.cc,v 1.4 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### Debian Source Package Records - Parser implementation for Debian style @@ -13,9 +13,11 @@ #pragma implementation "apt-pkg/debsrcrecords.h" #endif +#include <apt-pkg/deblistparser.h> #include <apt-pkg/debsrcrecords.h> #include <apt-pkg/error.h> #include <apt-pkg/strutl.h> +#include <apt-pkg/configuration.h> /*}}}*/ // SrcRecordParser::Binaries - Return the binaries field /*{{{*/ @@ -23,43 +25,63 @@ /* This member parses the binaries field into a pair of class arrays and returns a list of strings representing all of the components of the binaries field. The returned array need not be freed and will be - reused by the next Binaries function call. */ + reused by the next Binaries function call. This function is commonly + used during scanning to find the right package */ const char **debSrcRecordParser::Binaries() { + // This should use Start/Stop too, it is supposed to be efficient after all. string Bins = Sect.FindS("Binary"); - char *Buf = Buffer; - unsigned int Bin = 0; - if (Bins.empty() == true) + if (Bins.empty() == true || Bins.length() >= sizeof(Buffer)) return 0; - // Strip any leading spaces - string::const_iterator Start = Bins.begin(); - for (; Start != Bins.end() && isspace(*Start) != 0; Start++); + strcpy(Buffer,Bins.c_str()); + if (TokSplitString(',',Buffer,StaticBinList, + sizeof(StaticBinList)/sizeof(StaticBinList[0])) == false) + return 0; + return (const char **)StaticBinList; +} + /*}}}*/ +// SrcRecordParser::BuildDepends - Return the Build-Depends information /*{{{*/ +// --------------------------------------------------------------------- +/* This member parses the build-depends information and returns a list of + package/version records representing the build dependency. The returned + array need not be freed and will be reused by the next call to this + function */ +bool debSrcRecordParser::BuildDepends(vector<pkgSrcRecords::Parser::BuildDepRec> &BuildDeps) +{ + unsigned int I; + const char *Start, *Stop; + BuildDepRec rec; + const char *fields[] = {"Build-Depends", + "Build-Depends-Indep", + "Build-Conflicts", + "Build-Conflicts-Indep"}; + + BuildDeps.clear(); - string::const_iterator Pos = Start; - while (Pos != Bins.end()) + for (I = 0; I < 4; I++) { - // Skip to the next ',' - for (; Pos != Bins.end() && *Pos != ','; Pos++); + if (Sect.Find(fields[I], Start, Stop) == false) + continue; - // Back remove spaces - string::const_iterator End = Pos; - for (; End > Start && (End[-1] == ',' || isspace(End[-1]) != 0); End--); - - // Stash the string - memcpy(Buf,Start,End-Start); - StaticBinList[Bin] = Buf; - Bin++; - Buf += End-Start; - *Buf++ = 0; - - // Advance pos - for (; Pos != Bins.end() && (*Pos == ',' || isspace(*Pos) != 0); Pos++); - Start = Pos; + while (1) + { + Start = debListParser::ParseDepends(Start, Stop, + rec.Package,rec.Version,rec.Op,true); + + if (Start == 0) + return _error->Error("Problem parsing dependency: %s", fields[I]); + rec.Type = I; + + if (rec.Package != "") + BuildDeps.push_back(rec); + + if (Start == Stop) + break; + } } - StaticBinList[Bin] = 0; - return StaticBinList; + return true; } /*}}}*/ // SrcRecordParser::Files - Return a list of files for this source /*{{{*/ @@ -95,6 +117,25 @@ bool debSrcRecordParser::Files(vector<pkgSrcRecords::File> &List) // Parse the size and append the directory F.Size = atoi(Size.c_str()); F.Path = Base + F.Path; + + // Try to guess what sort of file it is we are getting. + string::size_type Pos = F.Path.length()-1; + while (1) + { + string::size_type Tmp = F.Path.rfind('.',Pos); + if (Tmp == string::npos) + break; + F.Type = string(F.Path,Tmp+1,Pos-Tmp); + + if (F.Type == "gz" || F.Type == "bz2") + { + Pos = Tmp-1; + continue; + } + + break; + } + List.push_back(F); } diff --git a/apt-pkg/deb/debsrcrecords.h b/apt-pkg/deb/debsrcrecords.h index 50488d4b6..477fe4fe3 100644 --- a/apt-pkg/deb/debsrcrecords.h +++ b/apt-pkg/deb/debsrcrecords.h @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: debsrcrecords.h,v 1.5 1999/10/18 04:15:25 jgg Exp $ +// $Id: debsrcrecords.h,v 1.6 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### Debian Source Package Records - Parser implementation for Debian style @@ -17,13 +17,15 @@ #include <apt-pkg/srcrecords.h> #include <apt-pkg/tagfile.h> +#include <apt-pkg/fileutl.h> class debSrcRecordParser : public pkgSrcRecords::Parser { + FileFd Fd; pkgTagFile Tags; pkgTagSection Sect; char Buffer[10000]; - const char *StaticBinList[400]; + char *StaticBinList[400]; unsigned long iOffset; public: @@ -32,11 +34,12 @@ class debSrcRecordParser : public pkgSrcRecords::Parser virtual bool Step() {iOffset = Tags.Offset(); return Tags.Step(Sect);}; virtual bool Jump(unsigned long Off) {iOffset = Off; return Tags.Jump(Sect,Off);}; - virtual string Package() {return Sect.FindS("Package");}; - virtual string Version() {return Sect.FindS("Version");}; - virtual string Maintainer() {return Sect.FindS("Maintainer");}; - virtual string Section() {return Sect.FindS("Section");}; + virtual string Package() const {return Sect.FindS("Package");}; + virtual string Version() const {return Sect.FindS("Version");}; + virtual string Maintainer() const {return Sect.FindS("Maintainer");}; + virtual string Section() const {return Sect.FindS("Section");}; virtual const char **Binaries(); + virtual bool BuildDepends(vector<BuildDepRec> &BuildDeps); virtual unsigned long Offset() {return iOffset;}; virtual string AsStr() { @@ -45,10 +48,11 @@ class debSrcRecordParser : public pkgSrcRecords::Parser return string(Start,Stop); }; virtual bool Files(vector<pkgSrcRecords::File> &F); - - debSrcRecordParser(FileFd *File,pkgSourceList::const_iterator SrcItem) : - Parser(File,SrcItem), - Tags(*File,sizeof(Buffer)) {}; + + debSrcRecordParser(string File,pkgIndexFile const *Index) : + Parser(Index), + Fd(File,FileFd::ReadOnly), + Tags(&Fd,sizeof(Buffer)) {}; }; #endif diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc new file mode 100644 index 000000000..0abd4c8aa --- /dev/null +++ b/apt-pkg/deb/debsystem.cc @@ -0,0 +1,197 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: debsystem.cc,v 1.2 2001/02/20 07:03:17 jgg Exp $ +/* ###################################################################### + + System - Abstraction for running on different systems. + + Basic general structure.. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#ifdef __GNUG__ +#pragma implementation "apt-pkg/debsystem.h" +#endif + +#include <apt-pkg/debsystem.h> +#include <apt-pkg/debversion.h> +#include <apt-pkg/debindexfile.h> +#include <apt-pkg/dpkgpm.h> +#include <apt-pkg/configuration.h> +#include <apt-pkg/error.h> +#include <apt-pkg/fileutl.h> + +#include <sys/types.h> +#include <unistd.h> +#include <dirent.h> +#include <errno.h> + /*}}}*/ + +debSystem debSys; + +// System::debSystem - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +debSystem::debSystem() +{ + LockFD = -1; + LockCount = 0; + + Label = "Debian dpkg interface"; + VS = &debVS; +} + /*}}}*/ +// System::Lock - Get the lock /*{{{*/ +// --------------------------------------------------------------------- +/* This mirrors the operations dpkg does when it starts up. Note the + checking of the updates directory. */ +bool debSystem::Lock() +{ + // Disable file locking + if (_config->FindB("Debug::NoLocking",false) == true || LockCount > 1) + { + LockCount++; + return true; + } + + // Create the lockfile + string AdminDir = flNotFile(_config->Find("Dir::State::status")); + LockFD = GetLock(AdminDir + "lock"); + if (LockFD == -1) + { + if (errno == EACCES || errno == EAGAIN) + return _error->Error("Unable to lock the administration directory (%s), " + "is another process using it?",AdminDir.c_str()); + else + return _error->Error("Unable to lock the administration directory (%s), " + "are you root?",AdminDir.c_str()); + } + + // See if we need to abort with a dirty journal + if (CheckUpdates() == true) + { + close(LockFD); + LockFD = -1; + return _error->Error("dpkg was interrupted, you must manually " + "run 'dpkg --configure -a' to correct the problem. "); + } + + LockCount++; + + return true; +} + /*}}}*/ +// System::UnLock - Drop a lock /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debSystem::UnLock(bool NoErrors) +{ + if (LockCount == 0 && NoErrors == true) + return false; + + if (LockCount < 1) + return _error->Error("Not locked"); + if (--LockCount == 0) + { + close(LockFD); + LockCount = 0; + } + + return true; +} + /*}}}*/ +// System::CheckUpdates - Check if the updates dir is dirty /*{{{*/ +// --------------------------------------------------------------------- +/* This does a check of the updates directory (dpkg journal) to see if it has + any entries in it. */ +bool debSystem::CheckUpdates() +{ + // Check for updates.. (dirty) + string File = flNotFile(_config->Find("Dir::State::status")) + "updates/"; + DIR *DirP = opendir(File.c_str()); + if (DirP == 0) + return false; + + /* We ignore any files that are not all digits, this skips .,.. and + some tmp files dpkg will leave behind.. */ + bool Damaged = false; + for (struct dirent *Ent = readdir(DirP); Ent != 0; Ent = readdir(DirP)) + { + Damaged = true; + for (unsigned int I = 0; Ent->d_name[I] != 0; I++) + { + // Check if its not a digit.. + if (isdigit(Ent->d_name[I]) == 0) + { + Damaged = false; + break; + } + } + if (Damaged == true) + break; + } + closedir(DirP); + + return Damaged; +} + /*}}}*/ +// System::CreatePM - Create the underlying package manager /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgPackageManager *debSystem::CreatePM(pkgDepCache *Cache) const +{ + return new pkgDPkgPM(Cache); +} + /*}}}*/ +// System::Initialize - Setup the configuration space.. /*{{{*/ +// --------------------------------------------------------------------- +/* These are the Debian specific configuration variables.. */ +bool debSystem::Initialize(Configuration &Cnf) +{ + /* These really should be jammed into a generic 'Local Database' engine + which is yet to be determined. The functions in pkgcachegen should + be the only users of these */ + Cnf.CndSet("Dir::State::userstatus","status.user"); // Defunct + Cnf.CndSet("Dir::State::status","/var/lib/dpkg/status"); + Cnf.CndSet("Dir::Bin::dpkg","/usr/bin/dpkg"); + + return true; +} + /*}}}*/ +// System::ArchiveSupported - Is a file format supported /*{{{*/ +// --------------------------------------------------------------------- +/* The standard name for a deb is 'deb'.. There are no seperate versions + of .deb to worry about.. */ +bool debSystem::ArchiveSupported(const char *Type) +{ + if (strcmp(Type,"deb") == 0) + return true; + return false; +} + /*}}}*/ +// System::Score - Determine how 'Debiany' this sys is.. /*{{{*/ +// --------------------------------------------------------------------- +/* We check some files that are sure tell signs of this being a Debian + System.. */ +signed debSystem::Score(Configuration const &Cnf) +{ + signed Score = 0; + if (FileExists(Cnf.FindFile("Dir::State::status","/var/lib/dpkg/status")) == true) + Score += 10; + if (FileExists(Cnf.FindFile("Dir::Bin::dpkg","/usr/bin/dpkg")) == true) + Score += 10; + if (FileExists("/etc/debian_version") == true) + Score += 10; + return Score; +} + /*}}}*/ +// System::AddStatusFiles - Register the status files /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debSystem::AddStatusFiles(vector<pkgIndexFile *> &List) +{ + List.push_back(new debStatusIndex(_config->FindFile("Dir::State::status"))); + return true; +} + /*}}}*/ diff --git a/apt-pkg/deb/debsystem.h b/apt-pkg/deb/debsystem.h new file mode 100644 index 000000000..4fd267f77 --- /dev/null +++ b/apt-pkg/deb/debsystem.h @@ -0,0 +1,41 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: debsystem.h,v 1.2 2001/02/20 07:03:17 jgg Exp $ +/* ###################################################################### + + System - Debian version of the System Class + + ##################################################################### */ + /*}}}*/ +#ifndef PKGLIB_DEBSYSTEM_H +#define PKGLIB_DEBSYSTEM_H + +#ifdef __GNUG__ +#pragma interface "apt-pkg/debsystem.h" +#endif + +#include <apt-pkg/pkgsystem.h> + +class debSystem : public pkgSystem +{ + // For locking support + int LockFD; + unsigned LockCount; + bool CheckUpdates(); + + public: + + virtual bool Lock(); + virtual bool UnLock(bool NoErrors = false); + virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const; + virtual bool Initialize(Configuration &Cnf); + virtual bool ArchiveSupported(const char *Type); + virtual signed Score(Configuration const &Cnf); + virtual bool AddStatusFiles(vector<pkgIndexFile *> &List); + + debSystem(); +}; + +extern debSystem debSys; + +#endif diff --git a/apt-pkg/deb/debversion.cc b/apt-pkg/deb/debversion.cc new file mode 100644 index 000000000..e7c42fd11 --- /dev/null +++ b/apt-pkg/deb/debversion.cc @@ -0,0 +1,266 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: debversion.cc,v 1.2 2001/02/20 07:03:17 jgg Exp $ +/* ###################################################################### + + Debian Version - Versioning system for Debian + + This implements the standard Debian versioning system. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#define APT_COMPATIBILITY 986 +#ifdef __GNUG__ +#pragma implementation "apt-pkg/debversion.h" +#endif + +#include <apt-pkg/debversion.h> +#include <apt-pkg/pkgcache.h> + +#include <stdlib.h> + /*}}}*/ + +debVersioningSystem debVS; + +// debVS::debVersioningSystem - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +debVersioningSystem::debVersioningSystem() +{ + Label = "Standard .deb"; +} + /*}}}*/ +// StrToLong - Convert the string between two iterators to a long /*{{{*/ +// --------------------------------------------------------------------- +/* */ +static unsigned long StrToLong(const char *begin,const char *end) +{ + char S[40]; + char *I = S; + for (; begin != end && I < S + 40;) + *I++ = *begin++; + *I = 0; + return strtoul(S,0,10); +} + /*}}}*/ +// debVS::CmpFragment - Compare versions /*{{{*/ +// --------------------------------------------------------------------- +/* This compares a fragment of the version. Dpkg has a really short + version of this, but it is uh.. interesting to grok. */ +int debVersioningSystem::CmpFragment(const char *A,const char *AEnd, + const char *B,const char *BEnd) +{ + if (A >= AEnd && B >= BEnd) + return 0; + if (A >= AEnd) + return -1; + if (B >= BEnd) + return 1; + + /* Iterate over the whole string + What this does is to spilt the whole string into groups of + numeric and non numeric portions. For instance: + a67bhgs89 + Has 4 portions 'a', '67', 'bhgs', '89'. A more normal: + 2.7.2-linux-1 + Has '2', '.', '7', '.' ,'-linux-','1' */ + const char *lhs = A; + const char *rhs = B; + while (lhs != AEnd && rhs != BEnd) + { + // Starting points + const char *Slhs = lhs; + const char *Srhs = rhs; + + // Compute ending points were we have passed over the portion + bool Digit = (isdigit(*lhs) > 0?true:false); + for (;lhs != AEnd && (isdigit(*lhs) > 0?true:false) == Digit; lhs++); + for (;rhs != BEnd && (isdigit(*rhs) > 0?true:false) == Digit; rhs++); + + if (Digit == true) + { + // If the lhs has a digit and the rhs does not then < + if (rhs - Srhs == 0) + return -1; + + // Generate integers from the strings. + unsigned long Ilhs = StrToLong(Slhs,lhs); + unsigned long Irhs = StrToLong(Srhs,rhs); + if (Ilhs != Irhs) + { + if (Ilhs > Irhs) + return 1; + return -1; + } + } + else + { + // They are equal length so do a straight text compare + for (;Slhs != lhs && Srhs != rhs; Slhs++, Srhs++) + { + if (*Slhs != *Srhs) + { + /* We need to compare non alpha chars as higher than alpha + chars (a < !) */ + int lc = *Slhs; + int rc = *Srhs; + if (isalpha(lc) == 0) lc += 256; + if (isalpha(rc) == 0) rc += 256; + if (lc > rc) + return 1; + return -1; + } + } + + // If the lhs is shorter than the right it is 'less' + if (lhs - Slhs < rhs - Srhs) + return -1; + + // If the lhs is longer than the right it is 'more' + if (lhs - Slhs > rhs - Srhs) + return 1; + } + } + + // The strings must be equal + if (lhs == AEnd && rhs == BEnd) + return 0; + + // lhs is shorter + if (lhs == AEnd) + return -1; + + // rhs is shorter + if (rhs == BEnd) + return 1; + + // Shouldnt happen + return 1; +} + /*}}}*/ +// debVS::CmpVersion - Comparison for versions /*{{{*/ +// --------------------------------------------------------------------- +/* This fragments the version into E:V-R triples and compares each + portion separately. */ +int debVersioningSystem::DoCmpVersion(const char *A,const char *AEnd, + const char *B,const char *BEnd) +{ + // Strip off the epoch and compare it + const char *lhs = A; + const char *rhs = B; + for (;lhs != AEnd && *lhs != ':'; lhs++); + for (;rhs != BEnd && *rhs != ':'; rhs++); + if (lhs == AEnd) + lhs = A; + if (rhs == BEnd) + rhs = B; + + // Compare the epoch + int Res = CmpFragment(A,lhs,B,rhs); + if (Res != 0) + return Res; + + // Skip the : + if (lhs != A) + lhs++; + if (rhs != B) + rhs++; + + // Find the last - + const char *dlhs = AEnd-1; + const char *drhs = BEnd-1; + for (;dlhs > lhs && *dlhs != '-'; dlhs--); + for (;drhs > rhs && *drhs != '-'; drhs--); + + if (dlhs == lhs) + dlhs = AEnd; + if (drhs == rhs) + drhs = BEnd; + + // Compare the main version + Res = CmpFragment(lhs,dlhs,rhs,drhs); + if (Res != 0) + return Res; + + // Skip the - + if (dlhs != lhs) + dlhs++; + if (drhs != rhs) + drhs++; + + return CmpFragment(dlhs,AEnd,drhs,BEnd); +} + /*}}}*/ +// debVS::CheckDep - Check a single dependency /*{{{*/ +// --------------------------------------------------------------------- +/* This simply preforms the version comparison and switch based on + operator. If DepVer is 0 then we are comparing against a provides + with no version. */ +bool debVersioningSystem::CheckDep(const char *PkgVer, + int Op,const char *DepVer) +{ + if (DepVer == 0 || DepVer[0] == 0) + return true; + if (PkgVer == 0 || PkgVer[0] == 0) + return false; + + // Perform the actual comparision. + int Res = CmpVersion(PkgVer,DepVer); + switch (Op & 0x0F) + { + case pkgCache::Dep::LessEq: + if (Res <= 0) + return true; + break; + + case pkgCache::Dep::GreaterEq: + if (Res >= 0) + return true; + break; + + case pkgCache::Dep::Less: + if (Res < 0) + return true; + break; + + case pkgCache::Dep::Greater: + if (Res > 0) + return true; + break; + + case pkgCache::Dep::Equals: + if (Res == 0) + return true; + break; + + case pkgCache::Dep::NotEquals: + if (Res != 0) + return true; + break; + } + + return false; +} + /*}}}*/ +// debVS::UpstreamVersion - Return the upstream version string /*{{{*/ +// --------------------------------------------------------------------- +/* This strips all the debian specific information from the version number */ +string debVersioningSystem::UpstreamVersion(const char *Ver) +{ + // Strip off the bit before the first colon + const char *I = Ver; + for (; *I != 0 && *I != ':'; I++); + if (*I == ':') + Ver = I + 1; + + // Chop off the trailing - + I = Ver; + unsigned Last = strlen(Ver); + for (; *I != 0; I++) + if (*I == '-') + Last = I - Ver; + + return string(Ver,Last); +} + /*}}}*/ diff --git a/apt-pkg/deb/debversion.h b/apt-pkg/deb/debversion.h new file mode 100644 index 000000000..d313f78a6 --- /dev/null +++ b/apt-pkg/deb/debversion.h @@ -0,0 +1,72 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: debversion.h,v 1.2 2001/02/20 07:03:17 jgg Exp $ +/* ###################################################################### + + Debian Version - Versioning system for Debian + + This implements the standard Debian versioning system. + + ##################################################################### */ + /*}}}*/ +#ifndef PKGLIB_DEBVERSION_H +#define PKGLIB_DEBVERSION_H + +#ifdef __GNUG__ +#pragma interface "apt-pkg/debversion.h" +#endif + +#include <apt-pkg/version.h> + +class debVersioningSystem : public pkgVersioningSystem +{ + static int CmpFragment(const char *A, const char *AEnd, const char *B, + const char *BEnd); + + public: + + // Compare versions.. + virtual int DoCmpVersion(const char *A,const char *Aend, + const char *B,const char *Bend); + virtual bool CheckDep(const char *PkgVer,int Op,const char *DepVer); + virtual int DoCmpReleaseVer(const char *A,const char *Aend, + const char *B,const char *Bend) + { + return DoCmpVersion(A,Aend,B,Bend); + } + virtual string UpstreamVersion(const char *A); + + debVersioningSystem(); +}; + +extern debVersioningSystem debVS; + +#ifdef APT_COMPATIBILITY +#if APT_COMPATIBILITY != 986 +#warning "Using APT_COMPATIBILITY" +#endif + +inline int pkgVersionCompare(const char *A, const char *B) +{ + return debVS.CmpVersion(A,B); +} +inline int pkgVersionCompare(const char *A, const char *AEnd, + const char *B, const char *BEnd) +{ + return debVS.DoCmpVersion(A,AEnd,B,BEnd); +} +inline int pkgVersionCompare(string A,string B) +{ + return debVS.CmpVersion(A,B); +} +inline bool pkgCheckDep(const char *DepVer,const char *PkgVer,int Op) +{ + return debVS.CheckDep(PkgVer,Op,DepVer); +} +inline string pkgBaseVersion(const char *Ver) +{ + return debVS.UpstreamVersion(Ver); +} +#endif + +#endif diff --git a/apt-pkg/deb/dpkginit.cc b/apt-pkg/deb/dpkginit.cc deleted file mode 100644 index 576e1967a..000000000 --- a/apt-pkg/deb/dpkginit.cc +++ /dev/null @@ -1,119 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -// $Id: dpkginit.cc,v 1.5 1999/08/03 05:21:19 jgg Exp $ -/* ###################################################################### - - DPKG init - Initialize the dpkg stuff - - This class provides the locking mechanism used by dpkg for its - database area. It does the proper consistency checks and acquires the - correct kind of lock. - - ##################################################################### */ - /*}}}*/ -// Includes /*{{{*/ -#ifdef __GNUG__ -#pragma implementation "apt-pkg/dpkginit.h" -#endif -#include <apt-pkg/dpkginit.h> -#include <apt-pkg/error.h> -#include <apt-pkg/configuration.h> -#include <apt-pkg/fileutl.h> - -#include <sys/types.h> -#include <unistd.h> -#include <dirent.h> - /*}}}*/ - -// DpkgLock::pkgDpkgLock - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgDpkgLock::pkgDpkgLock(bool WithUpdates) -{ - LockFD = -1; - GetLock(WithUpdates); -} - /*}}}*/ -// DpkgLock::~pkgDpkgLock - Destructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgDpkgLock::~pkgDpkgLock() -{ - Close(); -} - /*}}}*/ -// DpkgLock::GetLock - Get the lock /*{{{*/ -// --------------------------------------------------------------------- -/* This mirrors the operations dpkg does when it starts up. Note the - checking of the updates directory. */ -bool pkgDpkgLock::GetLock(bool WithUpdates) -{ - // Disable file locking - if (_config->FindB("Debug::NoLocking",false) == true) - return true; - - Close(); - - // Create the lockfile - string AdminDir = flNotFile(_config->Find("Dir::State::status")); - LockFD = ::GetLock(AdminDir + "lock"); - if (LockFD == -1) - return _error->Error("Unable to lock the administration directory, " - "are you root?"); - - // See if we need to abort with a dirty journal - if (WithUpdates == true && CheckUpdates() == true) - { - Close(); - return _error->Error("dpkg was interrupted, you must manually " - "run 'dpkg --configure -a' to correct the problem. "); - } - - return true; -} - /*}}}*/ -// DpkgLock::Close - Close the lock /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void pkgDpkgLock::Close() -{ - close(LockFD); - LockFD = -1; -} - /*}}}*/ -// DpkgLock::CheckUpdates - Check if the updates dir is dirty /*{{{*/ -// --------------------------------------------------------------------- -/* This does a check of the updates directory to see if it has any entries - in it. */ -bool pkgDpkgLock::CheckUpdates() -{ - // Check for updates.. (dirty) - string File = flNotFile(_config->Find("Dir::State::status")) + "updates/"; - DIR *DirP = opendir(File.c_str()); - if (DirP == 0) - return false; - - /* We ignore any files that are not all digits, this skips .,.. and - some tmp files dpkg will leave behind.. */ - bool Damaged = false; - for (struct dirent *Ent = readdir(DirP); Ent != 0; Ent = readdir(DirP)) - { - Damaged = true; - for (unsigned int I = 0; Ent->d_name[I] != 0; I++) - { - // Check if its not a digit.. - if (isdigit(Ent->d_name[I]) == 0) - { - Damaged = false; - break; - } - } - if (Damaged == true) - break; - } - closedir(DirP); - - return Damaged; -} - /*}}}*/ - diff --git a/apt-pkg/deb/dpkginit.h b/apt-pkg/deb/dpkginit.h deleted file mode 100644 index 532ff6236..000000000 --- a/apt-pkg/deb/dpkginit.h +++ /dev/null @@ -1,34 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -// $Id: dpkginit.h,v 1.2 1999/07/26 17:46:08 jgg Exp $ -/* ###################################################################### - - DPKG init - Initialize the dpkg stuff - - This basically gets a lock in /var/lib/dpkg and checks the updates - directory - - ##################################################################### */ - /*}}}*/ -#ifndef PKGLIB_DPKGINIT_H -#define PKGLIB_DPKGINIT_H - -#ifdef __GNUG__ -#pragma interface "apt-pkg/dpkginit.h" -#endif - -class pkgDpkgLock -{ - int LockFD; - - public: - - bool CheckUpdates(); - bool GetLock(bool WithUpdates); - void Close(); - - pkgDpkgLock(bool WithUpdates = true); - ~pkgDpkgLock(); -}; - -#endif diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 09cf20440..34c19ef4b 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: dpkgpm.cc,v 1.17 2000/05/13 01:52:38 jgg Exp $ +// $Id: dpkgpm.cc,v 1.18 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### DPKG Package Manager - Provide an interface to dpkg @@ -14,7 +14,9 @@ #include <apt-pkg/dpkgpm.h> #include <apt-pkg/error.h> #include <apt-pkg/configuration.h> - +#include <apt-pkg/depcache.h> +#include <apt-pkg/strutl.h> + #include <unistd.h> #include <stdlib.h> #include <fcntl.h> @@ -28,7 +30,7 @@ // DPkgPM::pkgDPkgPM - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgDPkgPM::pkgDPkgPM(pkgDepCache &Cache) : pkgPackageManager(Cache) +pkgDPkgPM::pkgDPkgPM(pkgDepCache *Cache) : pkgPackageManager(Cache) { } /*}}}*/ @@ -141,6 +143,90 @@ bool pkgDPkgPM::RunScripts(const char *Cnf) } /*}}}*/ +// DPkgPM::SendV2Pkgs - Send version 2 package info /*{{{*/ +// --------------------------------------------------------------------- +/* This is part of the helper script communication interface, it sends + very complete information down to the other end of the pipe.*/ +bool pkgDPkgPM::SendV2Pkgs(FILE *F) +{ + fprintf(F,"VERSION 2\n"); + + /* Write out all of the configuration directives by walking the + configuration tree */ + const Configuration::Item *Top = _config->Tree(0); + for (; Top != 0;) + { + if (Top->Value.empty() == false) + { + fprintf(F,"%s=%s\n", + QuoteString(Top->FullTag(),"=\"\n").c_str(), + QuoteString(Top->Value,"\n").c_str()); + } + + if (Top->Child != 0) + { + Top = Top->Child; + continue; + } + + while (Top != 0 && Top->Next == 0) + Top = Top->Parent; + if (Top != 0) + Top = Top->Next; + } + fprintf(F,"\n"); + + // Write out the package actions in order. + for (vector<Item>::iterator I = List.begin(); I != List.end(); I++) + { + pkgDepCache::StateCache &S = Cache[I->Pkg]; + + fprintf(F,"%s ",I->Pkg.Name()); + // Current version + if (I->Pkg->CurrentVer == 0) + fprintf(F,"- "); + else + fprintf(F,"%s ",I->Pkg.CurrentVer().VerStr()); + + // Show the compare operator + // Target version + if (S.InstallVer != 0) + { + int Comp = 2; + if (I->Pkg->CurrentVer != 0) + Comp = S.InstVerIter(Cache).CompareVer(I->Pkg.CurrentVer()); + if (Comp < 0) + fprintf(F,"> "); + if (Comp == 0) + fprintf(F,"= "); + if (Comp > 0) + fprintf(F,"< "); + fprintf(F,"%s ",S.InstVerIter(Cache).VerStr()); + } + else + fprintf(F,"> - "); + + // Show the filename/operation + if (I->Op == Item::Install) + { + // No errors here.. + if (I->File[0] != '/') + fprintf(F,"**ERROR**\n"); + else + fprintf(F,"%s\n",I->File.c_str()); + } + if (I->Op == Item::Configure) + fprintf(F,"**CONFIGURE**\n"); + if (I->Op == Item::Remove || + I->Op == Item::Purge) + fprintf(F,"**REMOVE**\n"); + + if (ferror(F) != 0) + return false; + } + return true; +} + /*}}}*/ // DPkgPM::RunScriptsWithPkgs - Run scripts with package names on stdin /*{{{*/ // --------------------------------------------------------------------- /* This looks for a list of scripts to run from the configuration file @@ -158,7 +244,18 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) { if (Opts->Value.empty() == true) continue; - + + // Determine the protocol version + string OptSec = Opts->Value; + string::size_type Pos; + if ((Pos = OptSec.find(' ')) == string::npos || Pos == 0) + Pos = OptSec.length(); + else + Pos--; + OptSec = "DPkg::Tools::Options::" + string(Opts->Value.c_str(),Pos); + + unsigned int Version = _config->FindI(OptSec+"::Version",1); + // Create the pipes int Pipes[2]; if (pipe(Pipes) != 0) @@ -185,31 +282,44 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) _exit(100); } close(Pipes[0]); - FileFd Fd(Pipes[1]); - + FILE *F = fdopen(Pipes[1],"w"); + if (F == 0) + return _error->Errno("fdopen","Faild to open new FD"); + // Feed it the filenames. - for (vector<Item>::iterator I = List.begin(); I != List.end(); I++) + bool Die = false; + if (Version <= 1) { - // Only deal with packages to be installed from .deb - if (I->Op != Item::Install) - continue; - - // No errors here.. - if (I->File[0] != '/') - continue; - - /* Feed the filename of each package that is pending install - into the pipe. */ - if (Fd.Write(I->File.begin(),I->File.length()) == false || - Fd.Write("\n",1) == false) + for (vector<Item>::iterator I = List.begin(); I != List.end(); I++) { - kill(Process,SIGINT); - Fd.Close(); - ExecWait(Process,Opts->Value.c_str(),true); - return _error->Error("Failure running script %s",Opts->Value.c_str()); + // Only deal with packages to be installed from .deb + if (I->Op != Item::Install) + continue; + + // No errors here.. + if (I->File[0] != '/') + continue; + + /* Feed the filename of each package that is pending install + into the pipe. */ + fprintf(F,"%s\n",I->File.c_str()); + if (ferror(F) != 0) + { + Die = true; + break; + } } } - Fd.Close(); + else + Die = !SendV2Pkgs(F); + + fclose(F); + if (Die == true) + { + kill(Process,SIGINT); + ExecWait(Process,Opts->Value.c_str(),true); + return _error->Error("Failure running script %s",Opts->Value.c_str()); + } // Clean up the sub process if (ExecWait(Process,Opts->Value.c_str()) == false) @@ -384,8 +494,8 @@ bool pkgDPkgPM::Go() { RunScripts("DPkg::Post-Invoke"); if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV) - return _error->Error("Sub-process %s recieved a segmentation fault.",Args[0]); - + return _error->Error("Sub-process %s received a segmentation fault.",Args[0]); + if (WIFEXITED(Status) != 0) return _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status)); diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index 0cc32f731..761aac76b 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: dpkgpm.h,v 1.6 1999/07/30 06:15:14 jgg Exp $ +// $Id: dpkgpm.h,v 1.7 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### DPKG Package Manager - Provide an interface to dpkg @@ -16,6 +16,7 @@ #include <apt-pkg/packagemanager.h> #include <vector> +#include <stdio.h> class pkgDPkgPM : public pkgPackageManager { @@ -26,7 +27,7 @@ class pkgDPkgPM : public pkgPackageManager enum Ops {Install, Configure, Remove, Purge} Op; string File; PkgIterator Pkg; - Item(Ops Op,PkgIterator Pkg,string File = "") : Op(Op), + Item(Ops Op,PkgIterator Pkg,string File = "") : Op(Op), File(File), Pkg(Pkg) {}; Item() {}; @@ -36,6 +37,7 @@ class pkgDPkgPM : public pkgPackageManager // Helpers bool RunScripts(const char *Cnf); bool RunScriptsWithPkgs(const char *Cnf); + bool SendV2Pkgs(FILE *F); // The Actuall installation implementation virtual bool Install(PkgIterator Pkg,string File); @@ -46,7 +48,7 @@ class pkgDPkgPM : public pkgPackageManager public: - pkgDPkgPM(pkgDepCache &Cache); + pkgDPkgPM(pkgDepCache *Cache); virtual ~pkgDPkgPM(); }; |