You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

962 lines
31 KiB

// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
* merged changes from the conference Patches applied: * apt@arch.ubuntu.com/apt--experimental--0.6--base-0 tag of apt@arch.ubuntu.com/apt--MAIN--0--patch-1190 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-1 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-2 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-3 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-4 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-5 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-6 Creation of branch v0_6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-7 Merge working copy of v0.6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-8 0.6.0 is headed for experimental, not unstable * apt@arch.ubuntu.com/apt--experimental--0.6--patch-9 Date * apt@arch.ubuntu.com/apt--experimental--0.6--patch-10 Update LIB_APT_PKG_MAJOR * apt@arch.ubuntu.com/apt--experimental--0.6--patch-11 - Fix a heap corruption bug in pkgSrcRecords::pkgSrcRec... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-12 Resynch * apt@arch.ubuntu.com/apt--experimental--0.6--patch-13 * Merge apt 0.5.17 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-14 * Rearrange Release file authentication code to be more... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-15 * Convert distribution "../project/experimental" to "ex... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-16 Merge 1.11 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-17 Merge 1.7 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-18 Merge 1.10 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-19 * Make a number of Release file errors into warnings; f... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-20 * Add space between package names when multiple unauthe... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-21 * Provide apt-key with a secret keyring and a trustdb, ... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-22 * Fix typo in apt-key(8) (standard input is '-', not '/') * apt@arch.ubuntu.com/apt--experimental--0.6--patch-23 0.6.2 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-24 Resynch * apt@arch.ubuntu.com/apt--experimental--0.6--patch-25 * Fix MetaIndexURI for flat ("foo/") sources * apt@arch.ubuntu.com/apt--experimental--0.6--patch-26 0.6.3 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-27 * Use the top-level Release file in LoadReleaseInfo, ra... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-28 0.6.4 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-29 Clarify * apt@arch.ubuntu.com/apt--experimental--0.6--patch-30 * Move the authentication check into a separate functio... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-31 * Fix display of unauthenticated packages when they are... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-32 * Move the authentication check into a separate functio... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-33 * Restore the ugly hack I removed from indexRecords::Lo... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-34 0.6.6 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-35 * Forgot to revert part of the changes to tagfile in 0.... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-36 * Add a config option and corresponding command line option * apt@arch.ubuntu.com/apt--experimental--0.6--patch-37 0.6.8 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-38 hopefully avoid more segfaults * apt@arch.ubuntu.com/apt--experimental--0.6--patch-39 XXX * apt@arch.ubuntu.com/apt--experimental--0.6--patch-40 * Another tagfile workaround * apt@arch.ubuntu.com/apt--experimental--0.6--patch-41 * Use "Codename" (woody, sarge, etc.) to supply the val... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-42 * Support IMS requests of Release.gpg and Release * apt@arch.ubuntu.com/apt--experimental--0.6--patch-43 * Have pkgAcquireIndex calculate an MD5 sum if one is n... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-44 * Merge 0.5.18 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-45 apt (0.6.13) experimental; urgency=low * apt@arch.ubuntu.com/apt--experimental--0.6--patch-46 0.6.13 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-47 Merge 0.5.20 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-48 The source list works a bit differently in 0.6; fix the... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-49 * s/Debug::Acquire::gpg/&v/ * apt@arch.ubuntu.com/apt--experimental--0.6--patch-50 * Honor the [vendor] syntax in sources.list again (thou... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-51 * Don't ship vendors.list(5) since it isn't used yet * apt@arch.ubuntu.com/apt--experimental--0.6--patch-52 * Revert change from 0.6.10; it was right in the first ... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-53 * Fix some cases where the .gpg file could be left in p... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-54 Print a warning if gnupg is not installed * apt@arch.ubuntu.com/apt--experimental--0.6--patch-55 * Handle more IMS stuff correctly * apt@arch.ubuntu.com/apt--experimental--0.6--patch-56 0.6.17 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-57 * Merge 0.5.21 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-58 * Add new Debian Archive Automatic Signing Key to the d... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-59 0.6.18 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-60 * Merge 0.5.22 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-61 * Convert apt-key(8) to docbook XML * apt@arch.ubuntu.com/apt--experimental--0.6--patch-62 Merge 0.5.23 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-63 Remove bogus partial 0.5.22 changelog entry * apt@arch.ubuntu.com/apt--experimental--0.6--patch-64 Make the auth warning a bit less redundant * apt@arch.ubuntu.com/apt--experimental--0.6--patch-65 * Merge 0.5.24 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-66 * Make the unauthenticated packages prompt more intuiti... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-67 Merge 0.5.25 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-68 * Remove obsolete pkgIterator::TargetVer() (Closes: #230159) * apt@arch.ubuntu.com/apt--experimental--0.6--patch-69 * Reverse test in CheckAuth to match new prompt (Closes... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-70 Update version * apt@arch.ubuntu.com/apt--experimental--0.6--patch-71 Fix backwards sense of CheckAuth prompt * apt@arch.ubuntu.com/apt--experimental--0.6--patch-72 0.6.24 * apt@arch.ubuntu.com/apt--experimental--0.6--patch-73 Close bug * apt@arch.ubuntu.com/apt--experimental--0.6--patch-74 * Fix handling of two-part sources for sources.list deb... * apt@arch.ubuntu.com/apt--experimental--0.6--patch-75 0.6.25 * apt@packages.debian.org/apt--authentication--0--base-0 tag of apt@arch.ubuntu.com/apt--experimental--0.6--patch-75 * apt@packages.debian.org/apt--authentication--0--patch-1 Michael Vogt's merge of apt--experimental--0 onto apt--main--0 * apt@packages.debian.org/apt--authentication--0--patch-2 Merge from apt--main--0 * apt@packages.debian.org/apt--authentication--0--patch-3 Merge from main * apt@packages.debian.org/apt--authentication--0--patch-4 Merge from main * apt@packages.debian.org/apt--authentication--0--patch-5 Update version number in configure.in * apt@packages.debian.org/apt--authentication--0--patch-6 Merge from main * apt@packages.debian.org/apt--authentication--0--patch-7 Merge from main * apt@packages.debian.org/apt--authentication--0--patch-8 Merge from mvo's branch * apt@packages.debian.org/apt--authentication--0--patch-9 Merge from mvo's tree * apt@packages.debian.org/apt--authentication--0--patch-10 Merge from mvo * apt@packages.debian.org/apt--authentication--0--patch-11 Fix permissions AGAIN * apt@packages.debian.org/apt--bzip2-debs--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-30 * apt@packages.debian.org/apt--bzip2-debs--0--patch-1 Create baz branch * apt@packages.debian.org/apt--bzip2-debs--0--patch-2 Implement data.tar.bz2 support * apt@packages.debian.org/apt--main--0--patch-30 Fix changelog * apt@packages.debian.org/apt--main--0--patch-31 Fix permissions again * apt@packages.debian.org/apt--main--0--patch-32 Fix permissions again * apt@packages.debian.org/apt--main--0--patch-33 Use baz instead of tla * apt@packages.debian.org/apt--main--0--patch-34 Merge bzip2-debs branch * apt@packages.debian.org/apt--main--0--patch-35 Fix changelog * apt@packages.debian.org/apt--main--0--patch-36 untagged-source precious * apt@packages.debian.org/apt--main--0--patch-37 Add .arch-inventory files * apt@packages.debian.org/apt--main--0--patch-38 Fix permissions again * apt@packages.debian.org/apt--main--0--patch-39 Merge apt--authentication--0 * apt@packages.debian.org/apt--main--0--patch-40 Merge misc-abi-changes * apt@packages.debian.org/apt--main--0--patch-41 Merge from mvo * apt@packages.debian.org/apt--misc-abi-changes--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-16 * apt@packages.debian.org/apt--misc-abi-changes--0--patch-1 Fix apt-get -s remove to not display the candidate version * apt@packages.debian.org/apt--misc-abi-changes--0--patch-2 Merge from main * apt@packages.debian.org/apt--misc-abi-changes--0--patch-3 Use pid_t throughout to hold process IDs * michael.vogt@canonical.com--2004--laptop/apt--authentication-mvo--0--base-0 tag of michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-12 * michael.vogt@canonical.com--2004--laptop/apt--authentication-mvo--0--patch-1 * star-merged matt's changes (bz2 support for data-members in debs) * michael.vogt@canonical.com--2004--laptop/apt--authentication-mvo--0--patch-2 * ignore errors when a Packages.bz2/Sources.bz2 can't be found and try with Packages.gz/Sources.gz again * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-34 * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-1 * merged matt's tree (with all those apt-authentication changes) * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-2 don't display a error if a bzip2 package can not be downloaded, just ignore (Ign) it * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-3 * "chmod 755 cmdline/apt-key", changed version to 0.6.27ubuntu1 * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-4 * fix for a stupid merge error (from 0.5->0.6) * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-5 * unstable should really be hoary * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-6 * stronger dependencies for libapt-pkg-dev (depends on the source version of apt and apt-watch now) * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-7 * distro really should be hoary, not unstable :/ * michael.vogt@canonical.com--2004--laptop/apt--mvo--0--patch-8 * documented the "--allow-unauthenticated" switch * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-1 tag of apt@packages.debian.org/apt--authentication--0--base-0 * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-2 merged "tla apply-delta -A foo@ apt@arch.ubuntu.com/apt--MAIN--0--patch-1190 apt@arch.ubuntu.com/apt--MAIN--0--patch-1343" and cleaned up conflicts * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-3 * missing bits from the merge added * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-4 * star-merged with apt@packages.debian.org/apt--main--0 * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-5 * tree-synced to the apt--authentication tree * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-6 * use the ubuntu-key in this version * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-7 * imported the patches from mdz * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-8 * apt-get update --print-uris works now as before (fallback to 0.5.x behaviour) * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-9 * fix for the "if any source unauthenticated, all other sources are unauthenticated too" problem * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-10 * reworked the "--print-uris" patch. it no longer uses: "APT::Get::Print-URIs" in the library * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-11 * version of the library set to 3.6 * michael.vogt@canonical.com--2004/apt--authentication-mvo--0--patch-12 * changelog finallized, will upload to people.ubuntulinux.org/~mvo/apt-authentication * michael.vogt@canonical.com--2004/apt--main-authentication--0--base-0 tag of apt@packages.debian.org/apt--main--0--patch-22 * michael.vogt@canonical.com--2004/apt--main-authentication--0--patch-1 * star-merge from apt--experimental--0.6 * michael.vogt@canonical.com--2004/apt--main-authentication--0--patch-2 * compile failure fix for methods/http.cc, po-file fixes
18 years ago
// $Id: deblistparser.cc,v 1.29.2.5 2004/01/06 01:43:44 mdz Exp $
/* ######################################################################
Package Cache Generator - Generator for the cache structure.
This builds the cache structure from the abstract package list parser.
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
#include <config.h>
#include <apt-pkg/deblistparser.h>
#include <apt-pkg/error.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/cachefilter.h>
#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/crc-16.h>
#include <apt-pkg/md5.h>
#include <apt-pkg/mmap.h>
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/cacheiterators.h>
#include <apt-pkg/tagfile.h>
#include <apt-pkg/macros.h>
#include <stddef.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <vector>
#include <ctype.h>
/*}}}*/
using std::string;
static debListParser::WordList PrioList[] = {
{"required",pkgCache::State::Required},
{"important",pkgCache::State::Important},
{"standard",pkgCache::State::Standard},
{"optional",pkgCache::State::Optional},
{"extra",pkgCache::State::Extra},
{NULL, 0}};
// ListParser::debListParser - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* Provide an architecture and only this one and "all" will be accepted
in Step(), if no Architecture is given we will accept every arch
we would accept in general with checkArchitecture() */
debListParser::debListParser(FileFd *File, string const &Arch) : Tags(File),
Arch(Arch) {
if (Arch == "native")
this->Arch = _config->Find("APT::Architecture");
Architectures = APT::Configuration::getArchitectures();
MultiArchEnabled = Architectures.size() > 1;
}
/*}}}*/
// 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::Package - Return the package name /*{{{*/
// ---------------------------------------------------------------------
/* This is to return the name of the package this section describes */
string debListParser::Package() {
string const Result = Section.FindS("Package");
if(unlikely(Result.empty() == true))
_error->Error("Encountered a section with no Package: header");
return Result;
}
/*}}}*/
// ListParser::Architecture - Return the package arch /*{{{*/
// ---------------------------------------------------------------------
/* This will return the Architecture of the package this section describes */
string debListParser::Architecture() {
return Section.FindS("Architecture");
}
/*}}}*/
// ListParser::ArchitectureAll /*{{{*/
// ---------------------------------------------------------------------
/* */
bool debListParser::ArchitectureAll() {
return Section.FindS("Architecture") == "all";
}
/*}}}*/
// 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 Section.FindS("Version");
}
/*}}}*/
unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/
{
unsigned char MA;
string const MultiArch = Section.FindS("Multi-Arch");
if (MultiArch.empty() == true)
MA = pkgCache::Version::None;
else if (MultiArch == "same") {
if (ArchitectureAll() == true)
{
if (showErrors == true)
_error->Warning("Architecture: all package '%s' can't be Multi-Arch: same",
Section.FindS("Package").c_str());
MA = pkgCache::Version::None;
}
else
MA = pkgCache::Version::Same;
}
else if (MultiArch == "foreign")
MA = pkgCache::Version::Foreign;
else if (MultiArch == "allowed")
MA = pkgCache::Version::Allowed;
else
{
if (showErrors == true)
_error->Warning("Unknown Multi-Arch type '%s' for package '%s'",
MultiArch.c_str(), Section.FindS("Package").c_str());
MA = pkgCache::Version::None;
}
if (ArchitectureAll() == true)
MA |= pkgCache::Version::All;
return MA;
}
/*}}}*/
// ListParser::NewVersion - Fill in the version structure /*{{{*/
// ---------------------------------------------------------------------
/* */
bool debListParser::NewVersion(pkgCache::VerIterator &Ver)
{
// Parse the section
Ver->Section = UniqFindTagWrite("Section");
Ver->MultiArch = ParseMultiArch(true);
// Archive Size
Ver->Size = Section.FindULL("Size");
// Unpacked Size (in K)
Ver->InstalledSize = Section.FindULL("Installed-Size");
Ver->InstalledSize *= 1024;
// Priority
const char *Start;
const char *Stop;
if (Section.Find("Priority",Start,Stop) == true)
{
if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
Ver->Priority = pkgCache::State::Extra;
}
if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false)
return false;
if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false)
return false;
if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false)
return false;
if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false)
return false;
if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
return false;
if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false)
return false;
if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
return false;
if (ParseDepends(Ver,"Enhances",pkgCache::Dep::Enhances) == false)
return false;
// Obsolete.
if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false)
return false;
if (ParseProvides(Ver) == false)
return false;
return true;
}
/*}}}*/
// ListParser::Description - Return the description string /*{{{*/
// ---------------------------------------------------------------------
/* This is to return the string describing the package in debian
form. If this returns the blank string then the entry is assumed to
only describe package properties */
string debListParser::Description()
{
string const lang = DescriptionLanguage();
if (lang.empty())
return Section.FindS("Description");
else
return Section.FindS(string("Description-").append(lang).c_str());
}
/*}}}*/
// ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
// ---------------------------------------------------------------------
/* This is to return the string describing the language of
description. If this returns the blank string then the entry is
assumed to describe original description. */
string debListParser::DescriptionLanguage()
{
if (Section.FindS("Description").empty() == false)
return "";
std::vector<string> const lang = APT::Configuration::getLanguages(true);
for (std::vector<string>::const_iterator l = lang.begin();
l != lang.end(); ++l)
if (Section.FindS(string("Description-").append(*l).c_str()).empty() == false)
return *l;
return "";
}
/*}}}*/
// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
// ---------------------------------------------------------------------
/* This is to return the md5 string to allow the check if it is the right
description. If no Description-md5 is found in the section it will be
calculated.
*/
MD5SumValue debListParser::Description_md5()
{
string const value = Section.FindS("Description-md5");
if (value.empty() == true)
{
std::string const desc = Description() + "\n";
if (desc == "\n")
return MD5SumValue();
MD5Summation md5;
md5.Add(desc.c_str());
return md5.Result();
}
else if (likely(value.size() == 32))
{
if (likely(value.find_first_not_of("0123456789abcdefABCDEF") == string::npos))
return MD5SumValue(value);
_error->Error("Malformed Description-md5 line; includes invalid character '%s'", value.c_str());
return MD5SumValue();
}
_error->Error("Malformed Description-md5 line; doesn't have the required length (32 != %d) '%s'", (int)value.size(), value.c_str());
return MD5SumValue();
}
/*}}}*/
// 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)
Pkg->Section = UniqFindTagWrite("Section");
string const static myArch = _config->Find("APT::Architecture");
// Possible values are: "all", "native", "installed" and "none"
// The "installed" mode is handled by ParseStatus(), See #544481 and friends.
string const static essential = _config->Find("pkgCacheGen::Essential", "all");
if (essential == "all" ||
(essential == "native" && Pkg->Arch != 0 && myArch == Pkg.Arch()))
if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
return false;
if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false)
return false;
if (strcmp(Pkg.Name(),"apt") == 0)
{
if ((essential == "native" && Pkg->Arch != 0 && myArch == Pkg.Arch()) ||
essential == "all")
Pkg->Flags |= pkgCache::Flag::Essential | pkgCache::Flag::Important;
else
Pkg->Flags |= pkgCache::Flag::Important;
}
if (ParseStatus(Pkg,Ver) == false)
return false;
return true;
}
/*}}}*/
// ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
// ---------------------------------------------------------------------
/* */
unsigned short debListParser::VersionHash()
{
const char *Sections[] ={"Installed-Size",
"Depends",
"Pre-Depends",
// "Suggests",
// "Recommends",
"Conflicts",
"Breaks",
"Replaces",0};
unsigned long Result = INIT_FCS;
char S[1024];
for (const char * const *I = Sections; *I != 0; ++I)
{
const char *Start;
const char *End;
if (Section.Find(*I,Start,End) == false || End - Start >= (signed)sizeof(S))
continue;
/* Strip out any spaces from the text, this undoes dpkgs reformatting
of certain fields. dpkg also has the rather interesting notion of
reformatting depends operators < -> <= */
char *J = S;
for (; Start != End; ++Start)
{
if (isspace(*Start) != 0)
continue;
*J++ = tolower_ascii(*Start);
if ((*Start == '<' || *Start == '>') && Start[1] != *Start && Start[1] != '=')
*J++ = '=';
}
Result = AddCRC16(Result,S,J - S);
}
return Result;
}
/*}}}*/
// ListParser::ParseStatus - Parse the status field /*{{{*/
// ---------------------------------------------------------------------
/* 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,
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;
// UsePackage() is responsible for setting the flag in the default case
bool const static essential = _config->Find("pkgCacheGen::Essential", "") == "installed";
if (essential == true &&
Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
return false;
// 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::State::Unknown},
{"install",pkgCache::State::Install},
{"hold",pkgCache::State::Hold},
{"deinstall",pkgCache::State::DeInstall},
{"purge",pkgCache::State::Purge},
{NULL, 0}};
if (GrabWord(string(Start,I-Start),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::State::Ok},
{"reinstreq",pkgCache::State::ReInstReq},
{"hold",pkgCache::State::HoldInst},
{"hold-reinstreq",pkgCache::State::HoldReInstReq},
{NULL, 0}};
if (GrabWord(string(Start,I-Start),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::State::NotInstalled},
{"unpacked",pkgCache::State::UnPacked},
{"half-configured",pkgCache::State::HalfConfigured},
{"installed",pkgCache::State::Installed},
{"half-installed",pkgCache::State::HalfInstalled},
{"config-files",pkgCache::State::ConfigFiles},
{"triggers-awaited",pkgCache::State::TriggersAwaited},
{"triggers-pending",pkgCache::State::TriggersPending},
{"post-inst-failed",pkgCache::State::HalfConfigured},
{"removal-failed",pkgCache::State::HalfInstalled},
{NULL, 0}};
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
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::State::NotInstalled ||
Pkg->CurrentState == pkgCache::State::ConfigFiles))
{
if (Ver.end() == true)
_error->Warning("Encountered status field in a non-version description");
else
Pkg->CurrentVer = Ver.Index();
}
return true;
}
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;
}
/*}}}*/
// ListParser::ParseDepends - Parse a dependency element /*{{{*/
// ---------------------------------------------------------------------
/* This parses the dependency elements out of a standard string in place,
bit by bit. */
const char *debListParser::ParseDepends(const char *Start,const char *Stop,
std::string &Package,std::string &Ver,unsigned int &Op)
{ return ParseDepends(Start, Stop, Package, Ver, Op, false, true, false); }
const char *debListParser::ParseDepends(const char *Start,const char *Stop,
std::string &Package,std::string &Ver,unsigned int &Op,
bool const &ParseArchFlags)
{ return ParseDepends(Start, Stop, Package, Ver, Op, ParseArchFlags, true, false); }
const char *debListParser::ParseDepends(const char *Start,const char *Stop,
std::string &Package,std::string &Ver,unsigned int &Op,
bool const &ParseArchFlags, bool const &StripMultiArch)
{ return ParseDepends(Start, Stop, Package, Ver, Op, ParseArchFlags, StripMultiArch, false); }
const char *debListParser::ParseDepends(const char *Start,const char *Stop,
string &Package,string &Ver,
unsigned int &Op, bool const &ParseArchFlags,
bool const &StripMultiArch,
bool const &ParseRestrictionsList)
{
// Strip off leading space
for (;Start != Stop && isspace(*Start) != 0; ++Start);
// Parse off the package name
const char *I = Start;
for (;I != Stop && isspace(*I) == 0 && *I != '(' && *I != ')' &&
*I != ',' && *I != '|' && *I != '[' && *I != ']' &&
*I != '<' && *I != '>'; ++I);
// Malformed, no '('
if (I != Stop && *I == ')')
return 0;
if (I == Start)
return 0;
// Stash the package name
Package.assign(Start,I - Start);
// We don't want to confuse library users which can't handle MultiArch
string const arch = _config->Find("APT::Architecture");
if (StripMultiArch == true) {
size_t const found = Package.rfind(':');
if (found != string::npos &&
(strcmp(Package.c_str() + found, ":any") == 0 ||
strcmp(Package.c_str() + found, ":native") == 0 ||
strcmp(Package.c_str() + found + 1, arch.c_str()) == 0))
Package = Package.substr(0,found);
}
// Skip white space to the '('
for (;I != Stop && isspace(*I) != 0 ; I++);
// Parse a version
if (I != Stop && *I == '(')
{
// Skip the '('
for (I++; I != Stop && isspace(*I) != 0 ; I++);
if (I + 3 >= Stop)
return 0;
I = ConvertRelation(I,Op);
// Skip whitespace
for (;I != Stop && isspace(*I) != 0; I++);
Start = I;
I = (const char*) memchr(I, ')', Stop - I);
if (I == NULL || Start == I)
return 0;
// Skip trailing whitespace
const char *End = I;
for (; End > Start && isspace(End[-1]); End--);
Ver.assign(Start,End-Start);
I++;
}
else
{
Ver.clear();
Op = pkgCache::Dep::NoOp;
}
// Skip whitespace
for (;I != Stop && isspace(*I) != 0; I++);
if (ParseArchFlags == true)
{
APT::CacheFilter::PackageArchitectureMatchesSpecification matchesArch(arch, false);
// Parse an architecture
if (I != Stop && *I == '[')
{
++I;
// malformed
if (unlikely(I == Stop))
return 0;
const char *End = I;
bool Found = false;
bool NegArch = false;
while (I != Stop)
{
// look for whitespace or ending ']'
for (;End != Stop && !isspace(*End) && *End != ']'; ++End);
if (unlikely(End == Stop))
return 0;
if (*I == '!')
{
NegArch = true;
++I;
}
std::string arch(I, End);
if (arch.empty() == false && matchesArch(arch.c_str()) == true)
{
Found = true;
if (I[-1] != '!')
NegArch = false;
// we found a match, so fast-forward to the end of the wildcards
for (; End != Stop && *End != ']'; ++End);
}
if (*End++ == ']') {
I = End;
break;
}
I = End;
for (;I != Stop && isspace(*I) != 0; I++);
}
if (NegArch == true)
Found = !Found;
if (Found == false)
Package = ""; /* not for this arch */
}
// Skip whitespace
for (;I != Stop && isspace(*I) != 0; I++);
}
if (ParseRestrictionsList == true)
{
// Parse a restrictions list
if (I != Stop && *I == '<')
{
++I;
// malformed
if (unlikely(I == Stop))
return 0;
std::vector<string> const profiles = APT::Configuration::getBuildProfiles();
const char *End = I;
bool Found = false;
bool NegRestriction = false;
while (I != Stop)
{
// look for whitespace or ending '>'
for (;End != Stop && !isspace(*End) && *End != '>'; ++End);
if (unlikely(End == Stop))
return 0;
if (*I == '!')
{
NegRestriction = true;
++I;
}
std::string restriction(I, End);