diff options
Diffstat (limited to 'apt-pkg/deb')
-rw-r--r-- | apt-pkg/deb/deblistparser.cc | 255 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.h | 51 |
2 files changed, 306 insertions, 0 deletions
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc new file mode 100644 index 000000000..28298aa36 --- /dev/null +++ b/apt-pkg/deb/deblistparser.cc @@ -0,0 +1,255 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: deblistparser.cc,v 1.1 1998/07/04 05:58:08 jgg Exp $ +/* ###################################################################### + + Package Cache Generator - Generator for the cache structure. + + This builds the cache structure from the abstract package list parser. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <pkglib/deblistparser.h> +#include <pkglib/error.h> +#include <system.h> + /*}}}*/ + +// ListParser::debListParser - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +debListParser::debListParser(File &File) : Tags(File) +{ + Step(); +} + /*}}}*/ +// ListParser::FindTag - Find the tag and return a string /*{{{*/ +// --------------------------------------------------------------------- +/* */ +string debListParser::FindTag(const char *Tag) +{ + const char *Start; + const char *Stop; + if (Section.Find(Tag,Start,Stop) == false) + return string(); + return string(Start,Stop - Start); +} + /*}}}*/ +// ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/ +// --------------------------------------------------------------------- +/* */ +unsigned long debListParser::UniqFindTagWrite(const char *Tag) +{ + const char *Start; + const char *Stop; + if (Section.Find(Tag,Start,Stop) == false) + return 0; + return WriteUniqString(Start,Stop - Start); +} + /*}}}*/ +// ListParser::HandleFlag - Sets a flag variable based on a tag /*{{{*/ +// --------------------------------------------------------------------- +/* This checks the tag for true/false yes/no etc */ +bool debListParser::HandleFlag(const char *Tag,unsigned long &Flags, + unsigned long Flag) +{ + const char *Start; + const char *Stop; + if (Section.Find(Tag,Start,Stop) == false) + return true; + + int Set = 2; + if (strncasecmp(Start,"yes",Stop - Start) == 0) + Set = 1; + if (strncasecmp(Start,"true",Stop - Start) == 0) + Set = 1; + if (strncasecmp(Start,"no",Stop - Start) == 0) + Set = 0; + if (strncasecmp(Start,"false",Stop - Start) == 0) + Set = 0; + if (Set == 2) + { + _error->Warning("Unknown flag value"); + return true; + } + + if (Set == 0) + Flags &= ~Flag; + if (Set == 1) + Flags |= Flag; + return true; +} + /*}}}*/ +// ListParser::Package - Return the package name /*{{{*/ +// --------------------------------------------------------------------- +/* This is to return the name of the package this section describes */ +string debListParser::Package() +{ + string Result = FindTag("Package"); + if (Result.empty() == true) + _error->Error("Encoutered a section with no Package: header"); + return Result; +} + /*}}}*/ +// ListParser::Version - Return the version string /*{{{*/ +// --------------------------------------------------------------------- +/* This is to return the string describing the version in debian form, + epoch:upstream-release. If this returns the blank string then the + entry is assumed to only describe package properties */ +string debListParser::Version() +{ + return FindTag("Version"); +} + /*}}}*/ +// ListParser::NewPackage - Fill in the package structure /*{{{*/ +// --------------------------------------------------------------------- +/* This is called when a new package structure is created. It must fill + in the static package information. */ +bool debListParser::NewPackage(pkgCache::PkgIterator Pkg) +{ + // Debian doesnt have anything, everything is condionally megered + return true; +} + /*}}}*/ +// ListParser::NewVersion - Fill in the version structure /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debListParser::NewVersion(pkgCache::VerIterator Ver) +{ + return true; +} + /*}}}*/ +// ListParser::UsePackage - Update a package structure /*{{{*/ +// --------------------------------------------------------------------- +/* This is called to update the package with any new information + that might be found in the section */ +bool debListParser::UsePackage(pkgCache::PkgIterator Pkg, + pkgCache::VerIterator Ver) +{ + if (Pkg->Section == 0) + if ((Pkg->Section = UniqFindTagWrite("Section")) == 0) + return false; + if (HandleFlag("Essential",Pkg->Flags,pkgCache::Essential) == false) + return false; + if (HandleFlag("Immediate-Configure",Pkg->Flags,pkgCache::ImmediateConf) == false) + return false; + if (ParseStatus(Pkg,Ver) == false) + return false; + return true; +} + /*}}}*/ +// ListParser::ParseStatus - Parse the status feild /*{{{*/ +// --------------------------------------------------------------------- +/* Status lines are of the form, + Status: want flag status + want = unknown, install, hold, deinstall, purge + flag = ok, reinstreq, hold, hold-reinstreq + status = not-installed, unpacked, half-configured, uninstalled, + half-installed, config-files, post-inst-failed, + removal-failed, installed + + Some of the above are obsolete (I think?) flag = hold-* and + status = post-inst-failed, removal-failed at least. + */ +bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg, + pkgCache::VerIterator Ver) +{ + const char *Start; + const char *Stop; + if (Section.Find("Status",Start,Stop) == false) + return true; + + // Isolate the first word + const char *I = Start; + for(; I < Stop && *I != ' '; I++); + if (I >= Stop || *I != ' ') + return _error->Error("Malformed Status line"); + + // Process the want field + WordList WantList[] = {{"unknown",pkgCache::Unknown}, + {"install",pkgCache::Install}, + {"hold",pkgCache::Hold}, + {"deinstall",pkgCache::DeInstall}, + {"purge",pkgCache::Purge}}; + if (GrabWord(string(Start,I-Start),WantList, + _count(WantList),Pkg->SelectedState) == false) + return _error->Error("Malformed 1st word in the Status line"); + + // Isloate the next word + I++; + Start = I; + for(; I < Stop && *I != ' '; I++); + if (I >= Stop || *I != ' ') + return _error->Error("Malformed status line, no 2nd word"); + + // Process the flag field + WordList FlagList[] = {{"ok",pkgCache::Ok}, + {"reinstreq",pkgCache::ReInstReq}, + {"hold",pkgCache::HoldInst}, + {"hold-reinstreq",pkgCache::HoldReInstReq}}; + if (GrabWord(string(Start,I-Start),FlagList, + _count(FlagList),Pkg->InstState) == false) + return _error->Error("Malformed 2nd word in the Status line"); + + // Isloate the last word + I++; + Start = I; + for(; I < Stop && *I != ' '; I++); + if (I != Stop) + return _error->Error("Malformed Status line, no 3rd word"); + + // Process the flag field + WordList StatusList[] = {{"not-installed",pkgCache::NotInstalled}, + {"unpacked",pkgCache::UnPacked}, + {"half-configured",pkgCache::HalfConfigured}, + {"installed",pkgCache::Installed}, + {"uninstalled",pkgCache::UnInstalled}, + {"half-installed",pkgCache::HalfInstalled}, + {"config-files",pkgCache::ConfigFiles}, + {"post-inst-failed",pkgCache::HalfConfigured}, + {"removal-failed",pkgCache::HalfInstalled}}; + if (GrabWord(string(Start,I-Start),StatusList, + _count(StatusList),Pkg->CurrentState) == false) + return _error->Error("Malformed 3rd word in the Status line"); + + /* A Status line marks the package as indicating the current + version as well. Only if it is actually installed.. Otherwise + the interesting dpkg handling of the status file creates bogus + entries. */ + if (!(Pkg->CurrentState == pkgCache::NotInstalled || + Pkg->CurrentState == pkgCache::ConfigFiles)) + { + if (Ver.end() == true) + _error->Warning("Encountered status field in a non-version description"); + else + Pkg->CurrentVer = Ver.Index(); + } + + return true; +} + /*}}}*/ +// 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) +{ + for (int C = 0; C != Count; C++) + { + if (strcasecmp(Word.c_str(),List[C].Str) == 0) + { + Out = List[C].Val; + return true; + } + } + return false; +} + /*}}}*/ +// ListParser::Step - Move to the next section in the file /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debListParser::Step() +{ + return Tags.Step(Section); +} + /*}}}*/ diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h new file mode 100644 index 000000000..30eb869ad --- /dev/null +++ b/apt-pkg/deb/deblistparser.h @@ -0,0 +1,51 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: deblistparser.h,v 1.1 1998/07/04 05:58:08 jgg Exp $ +/* ###################################################################### + + Debian Package List Parser - This implements the abstract parser + interface for Debian package files + + ##################################################################### */ + /*}}}*/ +// Header section: pkglib +#ifndef PKGLIB_DEBLISTPARSER_H +#define PKGLIB_DEBLISTPARSER_H + +#include <pkglib/pkgcachegen.h> +#include <pkglib/tagfile.h> + +class debListParser : public pkgCacheGenerator::ListParser +{ + pkgTagFile Tags; + pkgTagSection Section; + + // Parser Helper + struct WordList + { + char *Str; + unsigned char Val; + }; + + string FindTag(const char *Tag); + unsigned long UniqFindTagWrite(const char *Tag); + bool HandleFlag(const char *Tag,unsigned long &Flags,unsigned long Flag); + bool ParseStatus(pkgCache::PkgIterator Pkg,pkgCache::VerIterator Ver); + bool GrabWord(string Word,WordList *List,int Count,unsigned char &Out); + + public: + + // These all operate against the current section + virtual string Package(); + virtual string Version(); + virtual bool NewVersion(pkgCache::VerIterator Ver); + virtual bool NewPackage(pkgCache::PkgIterator Pkg); + virtual bool UsePackage(pkgCache::PkgIterator Pkg, + pkgCache::VerIterator Ver); + + virtual bool Step(); + + debListParser(File &File); +}; + +#endif |