From 7d15572bc3124b15c043e38bdc3d90bcc94f108a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 19 Dec 2009 14:25:20 +0100 Subject: add optional gcc features as deprecated, unused and (un)likely --- apt-pkg/contrib/system.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/system.h b/apt-pkg/contrib/system.h index 7ec3d7feb..f68df6265 100644 --- a/apt-pkg/contrib/system.h +++ b/apt-pkg/contrib/system.h @@ -55,4 +55,26 @@ #define CLRFLAG(v,f) ((v) &=~FLAG(f)) #define CHKFLAG(v,f) ((v) & FLAG(f) ? true : false) +// some nice optional GNUC features +#if __GNUC__ >= 3 + #define __must_check __attribute__ ((warn_unused_result)) + #define __deprecated __attribute__ ((deprecated)) + /* likely() and unlikely() can be used to mark boolean expressions + as (not) likely true which will help the compiler to optimise */ + #define likely(x) __builtin_expect (!!(x), 1) + #define unlikely(x) __builtin_expect (!!(x), 0) +#else + #define __must_check /* no warn_unused_result */ + #define __deprecated /* no deprecated */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif + +// cold functions are unlikely() to be called +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4 + #define __cold __attribute__ ((__cold__)) +#else + #define __cold /* no cold marker */ +#endif + #endif -- cgit v1.2.3-70-g09d2 From 201d1fa0d25deeda77c2570ee5342eaf18499699 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 19 Dec 2009 14:27:21 +0100 Subject: mark the Error/Warning method as __cold --- apt-pkg/contrib/error.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index a3be6a575..d92e40e9c 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -52,6 +52,7 @@ #endif #include +#include using std::string; @@ -71,13 +72,13 @@ class GlobalError public: // Call to generate an error from a library call. - bool Errno(const char *Function,const char *Description,...) APT_MFORMAT2; - bool WarningE(const char *Function,const char *Description,...) APT_MFORMAT2; + bool Errno(const char *Function,const char *Description,...) APT_MFORMAT2 __cold; + bool WarningE(const char *Function,const char *Description,...) APT_MFORMAT2 __cold; /* A warning should be considered less severe than an error, and may be ignored by the client. */ - bool Error(const char *Description,...) APT_MFORMAT1; - bool Warning(const char *Description,...) APT_MFORMAT1; + bool Error(const char *Description,...) APT_MFORMAT1 __cold; + bool Warning(const char *Description,...) APT_MFORMAT1 __cold; // Simple accessors inline bool PendingError() {return PendingFlag;}; -- cgit v1.2.3-70-g09d2 From 5dd4c8b811d9c7bc33e50254811f5bc0fc37f872 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 23 Dec 2009 12:38:19 +0100 Subject: merge Goswin Brederlow "support download of index files for different archs" patch which includes the following big changes: - Declare the unused [vendor] field in sources.list as option field, e.g. deb [arch=amd64,i386 lang=en_GB have=fun] http://example.org - When fetching index files download them for all APT::Architectures (overrideable with the options field above) - Allow all architectures of APT::Architectures to be in the Cache - Add the architecture to status and progress informations - Add b= (Binary architecture) to policy This commit doesn't incude the "pin-hack" as the Group structure will take care of this (and does it already to some extend). --- apt-pkg/aptconfiguration.cc | 25 ++++ apt-pkg/aptconfiguration.h | 16 +++ apt-pkg/cdrom.cc | 34 ++--- apt-pkg/clean.cc | 6 +- apt-pkg/contrib/strutl.cc | 17 +++ apt-pkg/contrib/strutl.h | 1 + apt-pkg/deb/debindexfile.cc | 15 ++- apt-pkg/deb/debindexfile.h | 4 +- apt-pkg/deb/deblistparser.cc | 57 ++++++--- apt-pkg/deb/deblistparser.h | 2 +- apt-pkg/deb/debmetaindex.cc | 292 +++++++++++++++++++++++++++---------------- apt-pkg/deb/debmetaindex.h | 28 +++-- apt-pkg/metaindex.h | 4 +- apt-pkg/pkgcache.cc | 8 +- apt-pkg/sourcelist.cc | 81 ++++++------ apt-pkg/sourcelist.h | 8 +- apt-pkg/versionmatch.cc | 8 +- apt-pkg/versionmatch.h | 2 + 18 files changed, 394 insertions(+), 214 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 899004d9f..1ec526646 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -223,4 +224,28 @@ std::vector const Configuration::getLanguages(bool const &All, return codes; } /*}}}*/ +// getArchitectures - Return Vector of prefered Architectures /*{{{*/ +std::vector const Configuration::getArchitectures(bool const &Cached) { + using std::string; + + std::vector static archs; + if (likely(Cached == true) && archs.empty() == false) + return archs; + + string const arch = _config->Find("APT::Architecture"); + archs = _config->FindVector("APT::Architectures"); + if (archs.empty() == true || + std::find(archs.begin(), archs.end(), arch) == archs.end()) + archs.push_back(arch); + return archs; +} + /*}}}*/ +// checkArchitecture - are we interested in the given Architecture? /*{{{*/ +bool const Configuration::checkArchitecture(std::string const &Arch) { + if (Arch == "all") + return true; + std::vector const archs = getArchitectures(true); + return (std::find(archs.begin(), archs.end(), Arch) != archs.end()); +} + /*}}}*/ } diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index f2f04a39b..b6650e20c 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -66,6 +66,22 @@ public: /*{{{*/ std::vector static const getLanguages(bool const &All = false, bool const &Cached = true, char const * const Locale = 0); + /** \brief Returns a vector of Architectures we support + * + * \param Cached saves the result so we need to calculated it only once + * this parameter should ony be used for testing purposes. + * + * \return a vector of Architectures in prefered order + */ + std::vector static const getArchitectures(bool const &Cached = true); + + /** \brief Are we interested in the given Architecture? + * + * \param Arch we want to check + * \return true if we are interested, false otherwise + */ + bool static const checkArchitecture(std::string const &Arch); + /*}}}*/ }; /*}}}*/ diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index 72d8e4d41..271bca409 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -6,6 +6,8 @@ #include #include #include +#include + #include #include #include @@ -216,33 +218,23 @@ int pkgCdrom::Score(string Path) /* Here we drop everything that is not this machines arch */ bool pkgCdrom::DropBinaryArch(vector &List) { - char S[300]; - snprintf(S,sizeof(S),"/binary-%s/", - _config->Find("Apt::Architecture").c_str()); - + for (unsigned int I = 0; I < List.size(); I++) { const char *Str = List[I].c_str(); - - const char *Res; - if ((Res = strstr(Str,"/binary-")) == 0) + const char *Start, *End; + if ((Start = strstr(Str,"/binary-")) == 0) continue; - // Weird, remove it. - if (strlen(Res) < strlen(S)) - { - List.erase(List.begin() + I); - I--; - continue; - } - - // See if it is our arch - if (stringcmp(Res,Res + strlen(S),S) == 0) - continue; - - // Erase it + // Between Start and End is the architecture + Start += 8; + if ((End = strstr(Start,"/")) != 0 && Start != End && + APT::Configuration::checkArchitecture(string(Start, --End)) == true) + continue; // okay, architecture is accepted + + // not accepted -> Erase it List.erase(List.begin() + I); - I--; + --I; // the next entry is at the same index after the erase } return true; diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc index 0d1dfbf74..629afd7cf 100644 --- a/apt-pkg/clean.cc +++ b/apt-pkg/clean.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -26,7 +27,6 @@ bool pkgArchiveCleaner::Go(string Dir,pkgCache &Cache) { bool CleanInstalled = _config->FindB("APT::Clean-Installed",true); - string MyArch = _config->Find("APT::Architecture"); DIR *D = opendir(Dir.c_str()); if (D == 0) @@ -75,9 +75,9 @@ bool pkgArchiveCleaner::Go(string Dir,pkgCache &Cache) for (I = Start; *I != 0 && *I != '.' ;I++); if (*I != '.') continue; - string Arch = DeQuoteString(string(Start,I-Start)); + string const Arch = DeQuoteString(string(Start,I-Start)); - if (Arch != "all" && Arch != MyArch) + if (APT::Configuration::checkArchitecture(Arch) == false) continue; // Lookup the package diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 4c05f2df8..bed51881f 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -983,6 +983,23 @@ bool TokSplitString(char Tok,char *Input,char **List, return true; } /*}}}*/ +// ExplodeString - Split a string up into a vector /*{{{*/ +// --------------------------------------------------------------------- +/* This can be used to split a given string up into a vector, so the + propose is the same as in the method above and this one is a bit slower + also, but the advantage is that we an iteratable vector */ +vector ExplodeString(string const &haystack, char const &split) { + string::const_iterator start = haystack.begin(); + string::const_iterator end = start; + vector exploded; + do { + for (; end != haystack.end() && *end != split; ++end); + exploded.push_back(string(start, end)); + start = end; + } while (end != haystack.end() && (++end) != haystack.end()); + return exploded; +} + /*}}}*/ // RegexChoice - Simple regex list/list matcher /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index 2b2e147fb..3bdb65b4d 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -59,6 +59,7 @@ bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0) bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length); bool TokSplitString(char Tok,char *Input,char **List, unsigned long ListMax); +vector ExplodeString(string const &haystack, char const &split=','); void ioprintf(ostream &out,const char *format,...) APT_FORMAT2; void strprintf(string &out,const char *format,...) APT_FORMAT2; char *safe_snprintf(char *Buffer,char *End,const char *Format,...) APT_FORMAT3; diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 5beb83665..73d72c729 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -149,9 +149,12 @@ unsigned long debSourcesIndex::Size() const // PackagesIndex::debPackagesIndex - Contructor /*{{{*/ // --------------------------------------------------------------------- /* */ -debPackagesIndex::debPackagesIndex(string URI,string Dist,string Section,bool Trusted) : - pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section) +debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string const &Section, + bool const &Trusted, string const &Arch) : + pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section), Architecture(Arch) { + if (Architecture == "native") + Architecture = _config->Find("APT::Architecture"); } /*}}}*/ // PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/ @@ -171,6 +174,8 @@ string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const Res += " "; Res += Ver.ParentPkg().Name(); Res += " "; + Res += Ver.Arch(); + Res += " "; Res += Ver.VerStr(); return Res; } @@ -204,6 +209,8 @@ string debPackagesIndex::Info(const char *Type) const else Info += Dist + '/' + Section; Info += " "; + Info += Architecture; + Info += " "; Info += Type; return Info; } @@ -227,7 +234,7 @@ string debPackagesIndex::IndexURI(const char *Type) const } else Res = URI + "dists/" + Dist + '/' + Section + - "/binary-" + _config->Find("APT::Architecture") + '/'; + "/binary-" + Architecture + '/'; Res += Type; return Res; @@ -259,7 +266,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const { string PackageFile = IndexFile("Packages"); FileFd Pkg(PackageFile,FileFd::ReadOnly); - debListParser Parser(&Pkg); + debListParser Parser(&Pkg, Architecture); if (_error->PendingError() == true) return _error->Error("Problem opening %s",PackageFile.c_str()); diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index c0e8d7d8e..766e8b214 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -46,6 +46,7 @@ class debPackagesIndex : public pkgIndexFile string URI; string Dist; string Section; + string Architecture; string Info(const char *Type) const; string IndexFile(const char *Type) const; @@ -69,7 +70,8 @@ class debPackagesIndex : public pkgIndexFile virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const; virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; - debPackagesIndex(string URI,string Dist,string Section,bool Trusted); + debPackagesIndex(string const &URI, string const &Dist, string const &Section, + bool const &Trusted, string const &Arch = "native"); }; class debTranslationsIndex : public pkgIndexFile diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index fe68aec0b..b57eca813 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -32,10 +32,13 @@ static debListParser::WordList PrioList[] = {{"important",pkgCache::State::Impor // ListParser::debListParser - Constructor /*{{{*/ // --------------------------------------------------------------------- -/* */ -debListParser::debListParser(FileFd *File) : Tags(File) -{ - Arch = _config->Find("APT::architecture"); +/* 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"); } /*}}}*/ // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/ @@ -64,13 +67,19 @@ string debListParser::Package() { // --------------------------------------------------------------------- /* This will return the Architecture of the package this section describes Note that architecture "all" packages will get the architecture of the - Packages file parsed here */ + Packages file parsed here. */ string debListParser::Architecture() { string const Result = Section.FindS("Architecture"); - if (Result.empty() == true) - return Arch; - if (Result == "all") - return Arch; + if (Result.empty() == true || Result == "all") { + if (Arch.empty() == true) + /* FIXME: this is a problem for installed arch all + packages as we don't know from which arch this + package was installed - and therefore which + dependency this package resolves. */ + return _config->Find("APT::Architecture"); + else + return Arch; + } return Result; } /*}}}*/ @@ -199,8 +208,12 @@ bool debListParser::UsePackage(pkgCache::PkgIterator Pkg, { if (Pkg->Section == 0) Pkg->Section = UniqFindTagWrite("Section"); - if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false) - return false; + + // Packages which are not from "our" arch doesn't get the essential flag + string const static myArch = _config->Find("APT::Architecture"); + if (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; @@ -630,17 +643,23 @@ bool debListParser::Step() /* See if this is the correct Architecture, if it isn't then we drop the whole section. A missing arch tag only happens (in theory) inside the Status file, so that is a positive return */ - const char *Start; - const char *Stop; - if (Section.Find("Architecture",Start,Stop) == false) + string const Architecture = Section.FindS("Architecture"); + if (Architecture.empty() == true) return true; - //FIXME: Accept different Architectures here - if (stringcmp(Arch,Start,Stop) == 0) - return true; + if (Arch.empty() == true) + { + if (APT::Configuration::checkArchitecture(Architecture) == true) + return true; + } + else + { + if (Architecture == Arch) + return true; - if (stringcmp(Start,Stop,"all") == 0) - return true; + if (Architecture == "all") + return true; + } iOffset = Tags.Offset(); } diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 5f91e073e..cba4f8e5d 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -69,7 +69,7 @@ class debListParser : public pkgCacheGenerator::ListParser bool const &StripMultiArch = false); static const char *ConvertRelation(const char *I,unsigned int &Op); - debListParser(FileFd *File); + debListParser(FileFd *File, string const &Arch = ""); }; #endif diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 8f28f053b..eb01a0156 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -8,9 +8,11 @@ #include #include +#include + using namespace std; -string debReleaseIndex::Info(const char *Type, const string Section) const +string debReleaseIndex::Info(const char *Type, string const &Section, string const &Arch) const { string Info = ::URI::SiteOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') @@ -19,7 +21,11 @@ string debReleaseIndex::Info(const char *Type, const string Section) const Info += Dist; } else - Info += Dist + '/' + Section; + { + Info += Dist + '/' + Section; + if (Arch.empty() == true) + Info += " " + Arch; + } Info += " "; Info += Type; return Info; @@ -61,16 +67,21 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const return Res; } -string debReleaseIndex::IndexURISuffix(const char *Type, const string Section) const +string debReleaseIndex::IndexURISuffix(const char *Type, string const &Section, string const &Arch) const { string Res =""; if (Dist[Dist.size() - 1] != '/') - Res += Section + "/binary-" + _config->Find("APT::Architecture") + '/'; + { + if (Arch == "native") + Res += Section + "/binary-" + _config->Find("APT::Architecture") + '/'; + else + Res += Section + "/binary-" + Arch + '/'; + } return Res + Type; } -string debReleaseIndex::IndexURI(const char *Type, const string Section) const +string debReleaseIndex::IndexURI(const char *Type, string const &Section, string const &Arch) const { if (Dist[Dist.size() - 1] == '/') { @@ -82,10 +93,10 @@ string debReleaseIndex::IndexURI(const char *Type, const string Section) const return Res + Type; } else - return URI + "dists/" + Dist + '/' + IndexURISuffix(Type, Section); + return URI + "dists/" + Dist + '/' + IndexURISuffix(Type, Section, Arch); } -string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string Section) const +string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string &Section) const { string Res =""; if (Dist[Dist.size() - 1] != '/') @@ -93,7 +104,7 @@ string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string Sect return Res + Type; } -string debReleaseIndex::SourceIndexURI(const char *Type, const string Section) const +string debReleaseIndex::SourceIndexURI(const char *Type, const string &Section) const { string Res; if (Dist[Dist.size() - 1] == '/') @@ -108,44 +119,61 @@ string debReleaseIndex::SourceIndexURI(const char *Type, const string Section) c return URI + "dists/" + Dist + "/" + SourceIndexURISuffix(Type, Section); } -debReleaseIndex::debReleaseIndex(string URI,string Dist) -{ - this->URI = URI; - this->Dist = Dist; - this->Indexes = NULL; - this->Type = "deb"; +debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) { + this->URI = URI; + this->Dist = Dist; + this->Indexes = NULL; + this->Type = "deb"; } -debReleaseIndex::~debReleaseIndex() -{ - for (vector::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); I++) - delete *I; +debReleaseIndex::~debReleaseIndex() { + for (map >::const_iterator A = ArchEntries.begin(); + A != ArchEntries.end(); ++A) + for (vector::const_iterator S = A->second.begin(); + S != A->second.end(); ++S) + delete *S; } -vector * debReleaseIndex::ComputeIndexTargets() const -{ - vector * IndexTargets = new vector ; - for (vector ::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); - I++) - { - IndexTarget * Target = new IndexTarget(); - Target->ShortDesc = (*I)->IsSrc ? "Sources" : "Packages"; - Target->MetaKey - = (*I)->IsSrc ? SourceIndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section) - : IndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section); - Target->URI - = (*I)->IsSrc ? SourceIndexURI(Target->ShortDesc.c_str(), (*I)->Section) - : IndexURI(Target->ShortDesc.c_str(), (*I)->Section); - - Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section); - IndexTargets->push_back (Target); - } - return IndexTargets; +vector * debReleaseIndex::ComputeIndexTargets() const { + vector * IndexTargets = new vector ; + + map >::const_iterator const src = ArchEntries.find("source"); + if (src != ArchEntries.end()) { + vector const SectionEntries = src->second; + for (vector::const_iterator I = SectionEntries.begin(); + I != SectionEntries.end(); ++I) { + IndexTarget * Target = new IndexTarget(); + Target->ShortDesc = "Sources"; + Target->MetaKey = SourceIndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section); + Target->URI = SourceIndexURI(Target->ShortDesc.c_str(), (*I)->Section); + Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section); + IndexTargets->push_back (Target); + } + } + + // Only source release + if (IndexTargets->empty() == false && ArchEntries.size() == 1) + return IndexTargets; + + for (map >::const_iterator a = ArchEntries.begin(); + a != ArchEntries.end(); ++a) { + if (a->first == "source") + continue; + for (vector ::const_iterator I = a->second.begin(); + I != a->second.end(); ++I) { + IndexTarget * Target = new IndexTarget(); + Target->ShortDesc = "Packages"; + Target->MetaKey = IndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section, a->first); + Target->URI = IndexURI(Target->ShortDesc.c_str(), (*I)->Section, a->first); + Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section, a->first); + IndexTargets->push_back (Target); + } + } + + return IndexTargets; } /*}}}*/ -bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const +bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const { // special case for --print-uris if (GetAll) { @@ -170,23 +198,27 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const ComputeIndexTargets(), new indexRecords (Dist)); - // Queue the translations - std::vector const lang = APT::Configuration::getLanguages(true); - for (vector::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); I++) { - - if((*I)->IsSrc) - continue; - - for (vector::const_iterator l = lang.begin(); - l != lang.end(); l++) - { - debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str()); - i.GetIndexes(Owner); - } - } - - return true; + // Queue the translations + std::vector const lang = APT::Configuration::getLanguages(true); + map > sections; + for (map >::const_iterator a = ArchEntries.begin(); + a != ArchEntries.end(); ++a) { + if (a->first == "source") + continue; + for (vector::const_iterator I = a->second.begin(); + I != a->second.end(); I++) + sections[(*I)->Section].insert(lang.begin(), lang.end()); + } + + for (map >::const_iterator s = sections.begin(); + s != sections.end(); ++s) + for (set::const_iterator l = s->second.begin(); + l != s->second.end(); l++) { + debTranslationsIndex i = debTranslationsIndex(URI,Dist,s->first,(*l).c_str()); + i.GetIndexes(Owner); + } + + return true; } bool debReleaseIndex::IsTrusted() const @@ -203,71 +235,111 @@ bool debReleaseIndex::IsTrusted() const return false; } -vector *debReleaseIndex::GetIndexFiles() -{ - if (Indexes != NULL) - return Indexes; - - Indexes = new vector ; - std::vector const lang = APT::Configuration::getLanguages(true); - for (vector::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); I++) { - if ((*I)->IsSrc) - Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted())); - else - { - Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted())); - - for (vector::const_iterator l = lang.begin(); - l != lang.end(); l++) - Indexes->push_back(new debTranslationsIndex(URI,Dist,(*I)->Section,(*l).c_str())); - } - } +vector *debReleaseIndex::GetIndexFiles() { + if (Indexes != NULL) + return Indexes; + + Indexes = new vector ; + map >::const_iterator const src = ArchEntries.find("source"); + if (src != ArchEntries.end()) { + vector const SectionEntries = src->second; + for (vector::const_iterator I = SectionEntries.begin(); + I != SectionEntries.end(); I++) + Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted())); + } + + // Only source release + if (Indexes->empty() == false && ArchEntries.size() == 1) + return Indexes; + + std::vector const lang = APT::Configuration::getLanguages(true); + map > sections; + for (map >::const_iterator a = ArchEntries.begin(); + a != ArchEntries.end(); ++a) { + if (a->first == "source") + continue; + for (vector::const_iterator I = a->second.begin(); + I != a->second.end(); I++) { + Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted(), a->first)); + sections[(*I)->Section].insert(lang.begin(), lang.end()); + } + } + + for (map >::const_iterator s = sections.begin(); + s != sections.end(); ++s) + for (set::const_iterator l = s->second.begin(); + l != s->second.end(); l++) + Indexes->push_back(new debTranslationsIndex(URI,Dist,s->first,(*l).c_str())); + + return Indexes; +} - return Indexes; +void debReleaseIndex::PushSectionEntry(vector const &Archs, const debSectionEntry *Entry) { + for (vector::const_iterator a = Archs.begin(); + a != Archs.end(); ++a) + ArchEntries[*a].push_back(new debSectionEntry(Entry->Section, Entry->IsSrc)); + delete Entry; } -void debReleaseIndex::PushSectionEntry(const debSectionEntry *Entry) -{ - SectionEntries.push_back(Entry); +void debReleaseIndex::PushSectionEntry(string const &Arch, const debSectionEntry *Entry) { + ArchEntries[Arch].push_back(Entry); } -debReleaseIndex::debSectionEntry::debSectionEntry (string Section, bool IsSrc): Section(Section) -{ - this->IsSrc = IsSrc; +void debReleaseIndex::PushSectionEntry(const debSectionEntry *Entry) { + if (Entry->IsSrc == true) + PushSectionEntry("source", Entry); + else { + for (map >::iterator a = ArchEntries.begin(); + a != ArchEntries.end(); ++a) { + a->second.push_back(Entry); + } + } } +debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section, + bool const &IsSrc): Section(Section), IsSrc(IsSrc) +{} + class debSLTypeDebian : public pkgSourceList::Type { protected: - bool CreateItemInternal(vector &List,string URI, - string Dist,string Section, - bool IsSrc) const + bool CreateItemInternal(vector &List, string const &URI, + string const &Dist, string const &Section, + bool const &IsSrc, map const &Options) const { - for (vector::const_iterator I = List.begin(); + map::const_iterator const arch = Options.find("arch"); + vector const Archs = + (arch != Options.end()) ? ExplodeString(arch->second) : + APT::Configuration::getArchitectures(); + + for (vector::const_iterator I = List.begin(); I != List.end(); I++) { - // This check insures that there will be only one Release file - // queued for all the Packages files and Sources files it - // corresponds to. - if (strcmp((*I)->GetType(), "deb") == 0) + // We only worry about debian entries here + if (strcmp((*I)->GetType(), "deb") != 0) + continue; + + debReleaseIndex *Deb = (debReleaseIndex *) (*I); + /* This check insures that there will be only one Release file + queued for all the Packages files and Sources files it + corresponds to. */ + if (Deb->GetURI() == URI && Deb->GetDist() == Dist) { - debReleaseIndex *Deb = (debReleaseIndex *) (*I); - // This check insures that there will be only one Release file - // queued for all the Packages files and Sources files it - // corresponds to. - if (Deb->GetURI() == URI && Deb->GetDist() == Dist) - { - Deb->PushSectionEntry(new debReleaseIndex::debSectionEntry(Section, IsSrc)); - return true; - } + if (IsSrc == true) + Deb->PushSectionEntry("source", new debReleaseIndex::debSectionEntry(Section, IsSrc)); + else + Deb->PushSectionEntry(Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc)); + return true; } } // No currently created Release file indexes this entry, so we create a new one. // XXX determine whether this release is trusted or not - debReleaseIndex *Deb = new debReleaseIndex(URI,Dist); - Deb->PushSectionEntry (new debReleaseIndex::debSectionEntry(Section, IsSrc)); + debReleaseIndex *Deb = new debReleaseIndex(URI, Dist); + if (IsSrc == true) + Deb->PushSectionEntry ("source", new debReleaseIndex::debSectionEntry(Section, IsSrc)); + else + Deb->PushSectionEntry (Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc)); List.push_back(Deb); return true; } @@ -277,10 +349,11 @@ class debSLTypeDeb : public debSLTypeDebian { public: - bool CreateItem(vector &List,string URI, - string Dist,string Section) const + bool CreateItem(vector &List, string const &URI, + string const &Dist, string const &Section, + std::map const &Options) const { - return CreateItemInternal(List, URI, Dist, Section, false); + return CreateItemInternal(List, URI, Dist, Section, false, Options); } debSLTypeDeb() @@ -294,10 +367,11 @@ class debSLTypeDebSrc : public debSLTypeDebian { public: - bool CreateItem(vector &List,string URI, - string Dist,string Section) const + bool CreateItem(vector &List, string const &URI, + string const &Dist, string const &Section, + std::map const &Options) const { - return CreateItemInternal(List, URI, Dist, Section, true); + return CreateItemInternal(List, URI, Dist, Section, true, Options); } debSLTypeDebSrc() diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 8e6a1463b..360fa5419 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -5,40 +5,44 @@ #include #include +#include + class debReleaseIndex : public metaIndex { public: class debSectionEntry { public: - debSectionEntry (string Section, bool IsSrc); - bool IsSrc; - string Section; + debSectionEntry (string const &Section, bool const &IsSrc); + string const Section; + bool const IsSrc; }; private: - vector SectionEntries; + std::map > ArchEntries; public: - debReleaseIndex(string URI, string Dist); + debReleaseIndex(string const &URI, string const &Dist); ~debReleaseIndex(); - virtual string ArchiveURI(string File) const {return URI + File;}; - virtual bool GetIndexes(pkgAcquire *Owner, bool GetAll=false) const; + virtual string ArchiveURI(string const &File) const {return URI + File;}; + virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; vector * ComputeIndexTargets() const; - string Info(const char *Type, const string Section) const; + string Info(const char *Type, string const &Section, string const &Arch="") const; string MetaIndexInfo(const char *Type) const; string MetaIndexFile(const char *Types) const; string MetaIndexURI(const char *Type) const; - string IndexURI(const char *Type, const string Section) const; - string IndexURISuffix(const char *Type, const string Section) const; - string SourceIndexURI(const char *Type, const string Section) const; - string SourceIndexURISuffix(const char *Type, const string Section) const; + string IndexURI(const char *Type, string const &Section, string const &Arch="native") const; + string IndexURISuffix(const char *Type, string const &Section, string const &Arch="native") const; + string SourceIndexURI(const char *Type, const string &Section) const; + string SourceIndexURISuffix(const char *Type, const string &Section) const; virtual vector *GetIndexFiles(); virtual bool IsTrusted() const; + void PushSectionEntry(vector const &Archs, const debSectionEntry *Entry); + void PushSectionEntry(string const &Arch, const debSectionEntry *Entry); void PushSectionEntry(const debSectionEntry *Entry); }; diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 779b6ab14..1d2140799 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -33,8 +33,8 @@ class metaIndex virtual const char* GetType() const {return Type;} // Interface for acquire - virtual string ArchiveURI(string /*File*/) const = 0; - virtual bool GetIndexes(pkgAcquire *Owner, bool GetAll=false) const = 0; + virtual string ArchiveURI(string const& /*File*/) const = 0; + virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const = 0; virtual vector *GetIndexFiles() = 0; virtual bool IsTrusted() const = 0; diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 2b5f53f6f..c945c59bf 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -406,7 +406,7 @@ operator<<(ostream& out, pkgCache::PkgIterator Pkg) string candidate = string(Pkg.CandVersion() == 0 ? "none" : Pkg.CandVersion()); string newest = string(Pkg.VersionList().end() ? "none" : Pkg.VersionList().VerStr()); - out << Pkg.Name() << " < " << current; + out << Pkg.Name() << " [ " << Pkg.Arch() << " ] < " << current; if (current != candidate) out << " -> " << candidate; if ( newest != "none" && candidate != newest) @@ -699,7 +699,9 @@ string pkgCache::VerIterator::RelStr() else Res += File.Site(); } - } + } + if (S->Arch != 0) + Res.append(" [").append(Arch()).append("]"); return Res; } /*}}}*/ @@ -738,6 +740,8 @@ string pkgCache::PkgFileIterator::RelStr() Res = Res + (Res.empty() == true?"l=":",l=") + Label(); if (Component() != 0) Res = Res + (Res.empty() == true?"c=":",c=") + Component(); + if (Architecture() != 0) + Res = Res + (Res.empty() == true?"b=":",b=") + Architecture(); return Res; } /*}}}*/ diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 4b3abe918..6b7a299d6 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -79,13 +79,51 @@ bool pkgSourceList::Type::FixupURI(string &URI) const Weird types may override this. */ bool pkgSourceList::Type::ParseLine(vector &List, const char *Buffer, - unsigned long CurLine, - string File) const + unsigned long const &CurLine, + string const &File) const { + for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces + + // Parse option field if it exists + // e.g.: [ option1=value1 option2=value2 ] + map Options; + if (Buffer != 0 && Buffer[0] == '[') + { + ++Buffer; // ignore the [ + for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces + while (*Buffer != ']') + { + // get one option, e.g. option1=value1 + string option; + if (ParseQuoteWord(Buffer,option) == false) + return _error->Error(_("Malformed line %lu in source list %s ([option] unparseable)"),CurLine,File.c_str()); + + if (option.length() < 3) + return _error->Error(_("Malformed line %lu in source list %s ([option] too short)"),CurLine,File.c_str()); + + size_t const needle = option.find('='); + if (needle == string::npos) + return _error->Error(_("Malformed line %lu in source list %s ([%s] is not an assignment)"),CurLine,File.c_str(), option.c_str()); + + string const key = string(option, 0, needle); + string const value = string(option, needle + 1, option.length()); + + if (key.empty() == true) + return _error->Error(_("Malformed line %lu in source list %s ([%s] has no key)"),CurLine,File.c_str(), option.c_str()); + + if (value.empty() == true) + return _error->Error(_("Malformed line %lu in source list %s ([%s] key %s has no value)"),CurLine,File.c_str(),option.c_str(),key.c_str()); + + Options[key] = value; + } + ++Buffer; // ignore the ] + for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces + } + string URI; string Dist; - string Section; - + string Section; + if (ParseQuoteWord(Buffer,URI) == false) return _error->Error(_("Malformed line %lu in source list %s (URI)"),CurLine,File.c_str()); if (ParseQuoteWord(Buffer,Dist) == false) @@ -100,7 +138,7 @@ bool pkgSourceList::Type::ParseLine(vector &List, if (ParseQuoteWord(Buffer,Section) == true) return _error->Error(_("Malformed line %lu in source list %s (absolute dist)"),CurLine,File.c_str()); Dist = SubstVar(Dist,"$(ARCH)",_config->Find("APT::Architecture")); - return CreateItem(List,URI,Dist,Section); + return CreateItem(List, URI, Dist, Section, Options); } // Grab the rest of the dists @@ -109,7 +147,7 @@ bool pkgSourceList::Type::ParseLine(vector &List, do { - if (CreateItem(List,URI,Dist,Section) == false) + if (CreateItem(List, URI, Dist, Section, Options) == false) return false; } while (ParseQuoteWord(Buffer,Section) == true); @@ -246,36 +284,7 @@ bool pkgSourceList::ReadAppend(string File) if (Parse == 0) return _error->Error(_("Type '%s' is not known on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str()); - // Vendor name specified - if (C[0] == '[') - { - string VendorID; - - if (ParseQuoteWord(C,VendorID) == false) - return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str()); - - if (VendorID.length() < 2 || VendorID.end()[-1] != ']') - return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str()); - VendorID = string(VendorID,1,VendorID.size()-2); - -// for (vector::const_iterator iter = VendorList.begin(); -// iter != VendorList.end(); iter++) -// { -// if ((*iter)->GetVendorID() == VendorID) -// { -// if (_config->FindB("Debug::sourceList", false)) -// std::cerr << "Comparing VendorID \"" << VendorID << "\" with \"" << (*iter)->GetVendorID() << '"' << std::endl; -// Verifier = *iter; -// break; -// } -// } - -// if (Verifier == 0) -// return _error->Error(_("Unknown vendor ID '%s' in line %u of source list %s"), -// VendorID.c_str(),CurLine,File.c_str()); - } - - if (Parse->ParseLine(SrcList,C,CurLine,File) == false) + if (Parse->ParseLine(SrcList, C, CurLine, File) == false) return false; } return true; diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h index b9e4389ed..e15314a5e 100644 --- a/apt-pkg/sourcelist.h +++ b/apt-pkg/sourcelist.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -57,9 +58,10 @@ class pkgSourceList bool FixupURI(string &URI) const; virtual bool ParseLine(vector &List, const char *Buffer, - unsigned long CurLine,string File) const; - virtual bool CreateItem(vector &List,string URI, - string Dist,string Section) const = 0; + unsigned long const &CurLine,string const &File) const; + virtual bool CreateItem(vector &List,string const &URI, + string const &Dist,string const &Section, + std::map const &Options) const = 0; Type(); virtual ~Type() {}; }; diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index b4d1d4696..e5f0fafd2 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -100,6 +100,8 @@ pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type) : Type(Type) RelLabel = Fragments[J]+2; else if (stringcasecmp(Fragments[J],Fragments[J]+2,"c=") == 0) RelComponent = Fragments[J]+2; + else if (stringcasecmp(Fragments[J],Fragments[J]+2,"b=") == 0) + RelArchitecture = Fragments[J]+2; } if (RelVerStr.end()[-1] == '*') @@ -178,7 +180,7 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) if (RelVerStr.empty() == true && RelOrigin.empty() == true && RelArchive.empty() == true && RelLabel.empty() == true && RelRelease.empty() == true && RelCodename.empty() == true && - RelComponent.empty() == true) + RelComponent.empty() == true && RelArchitecture.empty() == true) return false; if (RelVerStr.empty() == false) @@ -211,6 +213,10 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) if (File->Component == 0 || stringcasecmp(RelComponent,File.Component()) != 0) return false; + if (RelArchitecture.empty() == false) + if (File->Architecture == 0 || + stringcasecmp(RelArchitecture,File.Architecture()) != 0) + return false; return true; } diff --git a/apt-pkg/versionmatch.h b/apt-pkg/versionmatch.h index a8f3c84ac..a8da072ae 100644 --- a/apt-pkg/versionmatch.h +++ b/apt-pkg/versionmatch.h @@ -23,6 +23,7 @@ Codename (n=) e.g. etch, lenny, squeeze, sid Label (l=) Component (c=) + Binary Architecture (b=) If there are no equals signs in the string then it is scanned in short form - if it starts with a number it is Version otherwise it is an Archive or a Codename. @@ -55,6 +56,7 @@ class pkgVersionMatch string RelArchive; string RelLabel; string RelComponent; + string RelArchitecture; bool MatchAll; // Origin Matching -- cgit v1.2.3-70-g09d2 From 83742b3cf4b541fd61533dfecdc97e0e4502a7a4 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 14 Feb 2010 23:34:56 +0100 Subject: Add support for the LANGUAGE environment variable --- apt-pkg/aptconfiguration.cc | 91 ++++++++++++++++++++++++++-------------- apt-pkg/aptconfiguration.h | 2 +- apt-pkg/contrib/strutl.cc | 2 +- test/libapt/getlanguages_test.cc | 61 ++++++++++++++++++++------- 4 files changed, 108 insertions(+), 48 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 0fe84db74..f1989599b 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -8,10 +8,11 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#include #include #include +#include #include +#include #include #include @@ -97,7 +98,7 @@ const Configuration::getCompressionTypes(bool const &Cached) { will result in "de_DE, de, en". The special word "none" is the stopcode for the not-All code vector */ std::vector const Configuration::getLanguages(bool const &All, - bool const &Cached, char const * const Locale) { + bool const &Cached, char const ** const Locale) { using std::string; // The detection is boring and has a lot of cornercases, @@ -118,27 +119,29 @@ std::vector const Configuration::getLanguages(bool const &All, } } - // get the environment language code + // get the environment language codes: LC_MESSAGES (and later LANGUAGE) // we extract both, a long and a short code and then we will // check if we actually need both (rare) or if the short is enough - string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : Locale); + string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : *Locale); size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2; - size_t const lenLong = (envMsg.find('.') != string::npos) ? envMsg.find('.') : (lenShort + 3); + size_t const lenLong = (envMsg.find_first_of(".@") != string::npos) ? envMsg.find_first_of(".@") : (lenShort + 3); string envLong = envMsg.substr(0,lenLong); string const envShort = envLong.substr(0,lenShort); - bool envLongIncluded = true, envShortIncluded = false; + bool envLongIncluded = true; // first cornercase: LANG=C, so we use only "en" Translation if (envLong == "C") { codes.push_back("en"); + allCodes = codes; return codes; } + // to save the servers from unneeded queries, we only try also long codes + // for languages it is realistic to have a long code translation file… + // TODO: Improve translation acquire system to drop them dynamic + char const *needLong[] = { "cs", "en", "pt", "sv", "zh", NULL }; if (envLong != envShort) { - // to save the servers from unneeded queries, we only try also long codes - // for languages it is realistic to have a long code translation file... - char const *needLong[] = { "cs", "en", "pt", "sv", "zh", NULL }; for (char const **l = needLong; *l != NULL; l++) if (envShort.compare(*l) == 0) { envLongIncluded = false; @@ -156,33 +159,64 @@ std::vector const Configuration::getLanguages(bool const &All, if (oldAcquire.empty() == false && oldAcquire != "environment") { if (oldAcquire != "none") codes.push_back(oldAcquire); + allCodes = codes; return codes; } + // It is very likely we will need to environment codes later, + // so let us generate them now from LC_MESSAGES and LANGUAGE + std::vector environment; + // take care of LC_MESSAGES + if (envLongIncluded == false) + environment.push_back(envLong); + environment.push_back(envShort); + // take care of LANGUAGE + string envLang = Locale == 0 ? getenv("LANGUAGE") : *(Locale+1); + if (envLang.empty() == false) { + std::vector env = ExplodeString(envLang,':'); + short addedLangs = 0; // add a maximum of 3 fallbacks from the environment + for (std::vector::const_iterator e = env.begin(); + e != env.end() && addedLangs < 3; ++e) { + if (unlikely(e->empty() == true) || *e == "en") + continue; + if (*e == envLong || *e == envShort) + continue; + if (std::find(environment.begin(), environment.end(), *e) != environment.end()) + continue; + if (e->find('_') != string::npos) { + // Drop LongCodes here - ShortCodes are also included + string const shorty = e->substr(0, e->find('_')); + char const **n = needLong; + for (; *n != NULL; ++n) + if (shorty == *n) + break; + if (*n == NULL) + continue; + } + ++addedLangs; + environment.push_back(*e); + } + } + // Support settings like Acquire::Translation=none on the command line to // override the configuration settings vector of languages. string const forceLang = _config->Find("Acquire::Languages",""); if (forceLang.empty() == false) { if (forceLang == "environment") { - if (envLongIncluded == false) - codes.push_back(envLong); - if (envShortIncluded == false) - codes.push_back(envShort); - return codes; + codes = environment; } else if (forceLang != "none") codes.push_back(forceLang); + allCodes = codes; return codes; } std::vector const lang = _config->FindVector("Acquire::Languages"); // the default setting -> "environment, en" if (lang.empty() == true) { - if (envLongIncluded == false) - codes.push_back(envLong); - if (envShortIncluded == false) - codes.push_back(envShort); + codes = environment; if (envShort != "en") codes.push_back("en"); + allCodes = codes; return codes; } @@ -192,26 +226,19 @@ std::vector const Configuration::getLanguages(bool const &All, for (std::vector::const_iterator l = lang.begin(); l != lang.end(); l++) { if (*l == "environment") { - if (envLongIncluded == true && envShortIncluded == true) - continue; - if (envLongIncluded == false) { - envLongIncluded = true; - if (noneSeen == false) - codes.push_back(envLong); - allCodes.push_back(envLong); - } - if (envShortIncluded == false) { - envShortIncluded = true; + for (std::vector::const_iterator e = environment.begin(); + e != environment.end(); ++e) { + if (std::find(allCodes.begin(), allCodes.end(), *e) != allCodes.end()) + continue; if (noneSeen == false) - codes.push_back(envShort); - allCodes.push_back(envShort); + codes.push_back(*e); + allCodes.push_back(*e); } continue; } else if (*l == "none") { noneSeen = true; continue; - } else if ((envLongIncluded == true && *l == envLong) || - (envShortIncluded == true && *l == envShort)) + } else if (std::find(allCodes.begin(), allCodes.end(), *l) != allCodes.end()) continue; if (noneSeen == false) diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index b6650e20c..dd339d841 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -64,7 +64,7 @@ public: /*{{{*/ * \return a vector of (all) Language Codes in the prefered usage order */ std::vector static const getLanguages(bool const &All = false, - bool const &Cached = true, char const * const Locale = 0); + bool const &Cached = true, char const ** const Locale = 0); /** \brief Returns a vector of Architectures we support * diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index b285a9f2e..d3d6e2739 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1012,7 +1012,7 @@ vector ExplodeString(string const &haystack, char const &split) { do { for (; end != haystack.end() && *end != split; ++end); exploded.push_back(string(start, end)); - start = end; + start = end + 1; } while (end != haystack.end() && (++end) != haystack.end()); return exploded; } diff --git a/test/libapt/getlanguages_test.cc b/test/libapt/getlanguages_test.cc index fd3c8269f..fb7afb4ef 100644 --- a/test/libapt/getlanguages_test.cc +++ b/test/libapt/getlanguages_test.cc @@ -16,75 +16,108 @@ void dumpVector(std::vector vec) { int main(int argc,char *argv[]) { - std::vector vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8"); + char const* env[2]; + env[0] = "de_DE.UTF-8"; + env[1] = ""; + std::vector vec = APT::Configuration::getLanguages(false, false, env); equals(vec.size(), 2); equals(vec[0], "de"); equals(vec[1], "en"); // Special: Check if the cache is actually in use - vec = APT::Configuration::getLanguages(false, true, "en_GB.UTF-8"); + env[0] = "en_GB.UTF-8"; + vec = APT::Configuration::getLanguages(false, true, env); equals(vec.size(), 2); equals(vec[0], "de"); equals(vec[1], "en"); - vec = APT::Configuration::getLanguages(false, false, "en_GB.UTF-8"); + env[0] = "en_GB.UTF-8"; + vec = APT::Configuration::getLanguages(false, false, env); equals(vec.size(), 2); equals(vec[0], "en_GB"); equals(vec[1], "en"); - vec = APT::Configuration::getLanguages(false, false, "pt_PR.UTF-8"); + env[0] = "tr_DE@euro"; + vec = APT::Configuration::getLanguages(false, false, env); + equals(vec.size(), 2); + equals(vec[0], "tr"); + equals(vec[1], "en"); + + env[0] = "de_NO"; + env[1] = "se_NO:en_GB:nb_NO:nb:no_NO:no:nn_NO:nn:da:sv:en"; + vec = APT::Configuration::getLanguages(false, false, env); + equals(vec.size(), 5); + equals(vec[0], "de"); + equals(vec[1], "en_GB"); + equals(vec[2], "nb"); + equals(vec[3], "no"); + equals(vec[4], "en"); + + env[0] = "pt_PR.UTF-8"; + env[1] = ""; + vec = APT::Configuration::getLanguages(false, false, env); equals(vec.size(), 3); equals(vec[0], "pt_PR"); equals(vec[1], "pt"); equals(vec[2], "en"); - vec = APT::Configuration::getLanguages(false, false, "ast_DE.UTF-8"); // bogus, but syntactical correct + env[0] = "ast_DE.UTF-8"; + vec = APT::Configuration::getLanguages(false, false, env); // bogus, but syntactical correct equals(vec.size(), 2); equals(vec[0], "ast"); equals(vec[1], "en"); - vec = APT::Configuration::getLanguages(false, false, "C"); + env[0] = "C"; + vec = APT::Configuration::getLanguages(false, false, env); equals(vec.size(), 1); equals(vec[0], "en"); _config->Set("Acquire::Languages::1", "environment"); _config->Set("Acquire::Languages::2", "en"); - vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8"); + env[0] = "de_DE.UTF-8"; + vec = APT::Configuration::getLanguages(false, false, env); equals(vec.size(), 2); equals(vec[0], "de"); equals(vec[1], "en"); _config->Set("Acquire::Languages::3", "de"); - vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8"); + env[0] = "de_DE.UTF-8"; + vec = APT::Configuration::getLanguages(false, false, env); equals(vec.size(), 2); equals(vec[0], "de"); equals(vec[1], "en"); _config->Set("Acquire::Languages::1", "none"); - vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8"); + env[0] = "de_DE.UTF-8"; + vec = APT::Configuration::getLanguages(false, false, env); equals(vec.size(), 0); - vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8"); + env[0] = "de_DE.UTF-8"; + vec = APT::Configuration::getLanguages(true, false, env); equals(vec[0], "en"); equals(vec[1], "de"); _config->Set("Acquire::Languages::1", "fr"); _config->Set("Acquire::Languages", "de_DE"); - vec = APT::Configuration::getLanguages(false, false, "de_DE.UTF-8"); + env[0] = "de_DE.UTF-8"; + vec = APT::Configuration::getLanguages(false, false, env); equals(vec.size(), 1); equals(vec[0], "de_DE"); _config->Set("Acquire::Languages", "none"); - vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8"); + env[0] = "de_DE.UTF-8"; + vec = APT::Configuration::getLanguages(true, false, env); equals(vec.size(), 0); _config->Set("Acquire::Languages", ""); //FIXME: Remove support for this deprecated setting _config->Set("APT::Acquire::Translation", "ast_DE"); - vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8"); + env[0] = "de_DE.UTF-8"; + vec = APT::Configuration::getLanguages(true, false, env); equals(vec.size(), 1); equals(vec[0], "ast_DE"); _config->Set("APT::Acquire::Translation", "none"); - vec = APT::Configuration::getLanguages(true, false, "de_DE.UTF-8"); + env[0] = "de_DE.UTF-8"; + vec = APT::Configuration::getLanguages(true, false, env); equals(vec.size(), 0); return 0; -- cgit v1.2.3-70-g09d2 From 06afffcc24f339e8735acd4698af6e5995ad24aa Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 27 Feb 2010 02:02:25 +0100 Subject: * apt-pkg/contrib/mmap.{h,cc}: - add char[] fallback for filesystems without shared writable mmap() like JFFS2. Thanks to Marius Vollmer for writing and to Loïc Minier for pointing to the patch! (Closes: #314334) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apt-pkg/contrib/mmap.cc | 70 +++++++++++++++++++++++++++++++++++++++++-------- apt-pkg/contrib/mmap.h | 5 ++++ debian/changelog | 4 +++ 3 files changed, 68 insertions(+), 11 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index f440f9489..b3f29032c 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -27,6 +27,7 @@ #include #include #include +#include #include /*}}}*/ @@ -35,7 +36,7 @@ // --------------------------------------------------------------------- /* */ MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0), - Base(0) + Base(0), SyncToFd(NULL) { if ((Flags & NoImmMap) != NoImmMap) Map(F); @@ -45,7 +46,7 @@ MMap::MMap(FileFd &F,unsigned long Flags) : Flags(Flags), iSize(0), // --------------------------------------------------------------------- /* */ MMap::MMap(unsigned long Flags) : Flags(Flags), iSize(0), - Base(0) + Base(0), SyncToFd(NULL) { } /*}}}*/ @@ -78,7 +79,24 @@ bool MMap::Map(FileFd &Fd) // Map it. Base = mmap(0,iSize,Prot,Map,Fd.Fd(),0); if (Base == (void *)-1) - return _error->Errno("mmap",_("Couldn't make mmap of %lu bytes"),iSize); + { + if (errno == ENODEV || errno == EINVAL) + { + // The filesystem doesn't support this particular kind of mmap. + // So we allocate a buffer and read the whole file into it. + int const dupped_fd = dup(Fd.Fd()); + if (dupped_fd == -1) + return _error->Errno("mmap", _("Couldn't duplicate file descriptor %i"), Fd.Fd()); + + Base = new unsigned char[iSize]; + SyncToFd = new FileFd (dupped_fd); + if (!SyncToFd->Seek(0L) || !SyncToFd->Read(Base, iSize)) + return false; + } + else + return _error->Errno("mmap",_("Couldn't make mmap of %lu bytes"), + iSize); + } return true; } @@ -93,10 +111,19 @@ bool MMap::Close(bool DoSync) if (DoSync == true) Sync(); - - if (munmap((char *)Base,iSize) != 0) - _error->Warning("Unable to munmap"); - + + if (SyncToFd != NULL) + { + delete[] (char *)Base; + delete SyncToFd; + SyncToFd = NULL; + } + else + { + if (munmap((char *)Base, iSize) != 0) + _error->WarningE("mmap", _("Unable to close mmap")); + } + iSize = 0; Base = 0; return true; @@ -113,8 +140,18 @@ bool MMap::Sync() #ifdef _POSIX_SYNCHRONIZED_IO if ((Flags & ReadOnly) != ReadOnly) - if (msync((char *)Base,iSize,MS_SYNC) < 0) - return _error->Errno("msync","Unable to write mmap"); + { + if (SyncToFd != NULL) + { + if (!SyncToFd->Seek(0) || !SyncToFd->Write(Base, iSize)) + return false; + } + else + { + if (msync((char *)Base, iSize, MS_SYNC) < 0) + return _error->Errno("msync", _("Unable to synchronize mmap")); + } + } #endif return true; } @@ -130,8 +167,19 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop) #ifdef _POSIX_SYNCHRONIZED_IO unsigned long PSize = sysconf(_SC_PAGESIZE); if ((Flags & ReadOnly) != ReadOnly) - if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) < 0) - return _error->Errno("msync","Unable to write mmap"); + { + if (SyncToFd != 0) + { + if (!SyncToFd->Seek(0) || + !SyncToFd->Write (((char *)Base)+Start, Stop-Start)) + return false; + } + else + { + if (msync((char *)Base+(int)(Start/PSize)*PSize,Stop - Start,MS_SYNC) < 0) + return _error->Errno("msync", _("Unable to synchronize mmap")); + } + } #endif return true; } diff --git a/apt-pkg/contrib/mmap.h b/apt-pkg/contrib/mmap.h index cd2b15ba2..5ca951204 100644 --- a/apt-pkg/contrib/mmap.h +++ b/apt-pkg/contrib/mmap.h @@ -44,6 +44,11 @@ class MMap unsigned long iSize; void *Base; + // In case mmap can not be used, we keep a dup of the file + // descriptor that should have been mmaped so that we can write to + // the file in Sync(). + FileFd *SyncToFd; + bool Map(FileFd &Fd); bool Close(bool DoSync = true); diff --git a/debian/changelog b/debian/changelog index 9fc481276..39cc70da9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,10 @@ apt (0.7.26) UNRELEASED; urgency=low - don't crash if no arguments are given (Closes: #570962) * debian/control: - remove some years old and obsolete Replaces + * apt-pkg/contrib/mmap.{h,cc}: + - add char[] fallback for filesystems without shared writable + mmap() like JFFS2. Thanks to Marius Vollmer for writing + and to Loïc Minier for pointing to the patch! (Closes: #314334) -- David Kalnischkies Fri, 19 Feb 2010 21:21:43 +0100 -- cgit v1.2.3-70-g09d2 From 2bb255740bf18b5e0524fe833523303abb5c9051 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 12 Mar 2010 19:41:30 +0100 Subject: * apt-pkg/deb/dpkgpm.cc: - if available store the Commandline in the history * apt-pkg/contrib/cmndline.cc: - save Commandline in Commandline::AsString for logging --- apt-pkg/contrib/cmndline.cc | 42 ++++++++++++++++++++++++++++++++- apt-pkg/contrib/cmndline.h | 1 + apt-pkg/deb/dpkgpm.cc | 2 ++ debian/changelog | 3 +++ test/libapt/commandlineasstring_test.cc | 39 ++++++++++++++++++++++++++++++ test/libapt/makefile | 6 +++++ 6 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 test/libapt/commandlineasstring_test.cc (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc index bfd53695e..0b16bf51a 100644 --- a/apt-pkg/contrib/cmndline.cc +++ b/apt-pkg/contrib/cmndline.cc @@ -135,7 +135,9 @@ bool CommandLine::Parse(int argc,const char **argv) for (; I != argc; I++) *Files++ = argv[I]; *Files = 0; - + + SaveInConfig(argc, argv); + return true; } /*}}}*/ @@ -351,3 +353,41 @@ bool CommandLine::DispatchArg(Dispatch *Map,bool NoMatch) return false; } /*}}}*/ +// CommandLine::SaveInConfig - for output later in a logfile or so /*{{{*/ +// --------------------------------------------------------------------- +/* We save the commandline here to have it around later for e.g. logging. + It feels a bit like a hack here and isn't bulletproof, but it is better + than nothing after all. */ +void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * const argv) +{ + char cmdline[300]; + unsigned int length = 0; + bool lastWasOption = false; + bool closeQuote = false; + for (unsigned int i = 0; i < argc; ++i, ++length) + { + for (unsigned int j = 0; argv[i][j] != '\0' && length < sizeof(cmdline)-1; ++j, ++length) + { + cmdline[length] = argv[i][j]; + if (lastWasOption == true && argv[i][j] == '=') + { + // That is possibly an option: Quote it if it includes spaces, + // the benefit is that this will eliminate also most false positives + const char* c = &argv[i][j+1]; + for (; *c != '\0' && *c != ' '; ++c); + if (*c == '\0') continue; + cmdline[++length] = '"'; + closeQuote = true; + } + } + if (closeQuote == true) + cmdline[length++] = '"'; + // Problem: detects also --hello + if (cmdline[length-1] == 'o') + lastWasOption = true; + cmdline[length] = ' '; + } + cmdline[--length] = '\0'; + _config->Set("CommandLine::AsString", cmdline); +} + /*}}}*/ diff --git a/apt-pkg/contrib/cmndline.h b/apt-pkg/contrib/cmndline.h index e28071e81..7c0c71aa7 100644 --- a/apt-pkg/contrib/cmndline.h +++ b/apt-pkg/contrib/cmndline.h @@ -60,6 +60,7 @@ class CommandLine Configuration *Conf; bool HandleOpt(int &I,int argc,const char *argv[], const char *&Opt,Args *A,bool PreceedeMatch = false); + void static SaveInConfig(unsigned int const &argc, char const * const * const argv); public: diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index ad1ea77fd..9ba60060c 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -614,6 +614,8 @@ bool pkgDPkgPM::OpenLog() remove += I.Name() + string(" (") + Cache[I].CurVersion + string("), "); } } + if (_config->Exists("Commandline::AsString") == true) + WriteHistoryTag("Commandline", _config->Find("Commandline::AsString")); WriteHistoryTag("Install", install); WriteHistoryTag("Upgrade", upgrade); WriteHistoryTag("Downgrade",downgrade); diff --git a/debian/changelog b/debian/changelog index b05498f12..506e70a25 100644 --- a/debian/changelog +++ b/debian/changelog @@ -14,9 +14,12 @@ apt (0.7.26) UNRELEASED; urgency=low Thanks to Osamu Aoki for pointing it out! (Closes: #567669) * apt-pkg/deb/dpkgpm.cc: - fix error message construction in OpenLog() + - if available store the Commandline in the history * cmdline/apt-get.cc: - add a --only-upgrade flag to install command (Closes: #572259) - fix memory leaks in error conditions in DoSource() + * apt-pkg/contrib/cmndline.cc: + - save Commandline in Commandline::AsString for logging -- David Kalnischkies Fri, 19 Feb 2010 21:21:43 +0100 diff --git a/test/libapt/commandlineasstring_test.cc b/test/libapt/commandlineasstring_test.cc new file mode 100644 index 000000000..a38957d7e --- /dev/null +++ b/test/libapt/commandlineasstring_test.cc @@ -0,0 +1,39 @@ +#include +#include + +#include + +#include "assert.h" + +class CLT: public CommandLine { + + public: + std::string static AsString(const char * const * const argv, + unsigned int const argc) { + std::string const static conf = "Commandline::AsString"; + _config->Clear(conf); + SaveInConfig(argc, argv); + return _config->Find(conf); + } +}; + +#define CMD(y,z) equals(CLT::AsString(argv, y), z); + +int main() { + { + const char* const argv[] = {"apt-get", "install", "-sf"}; + CMD(3, "apt-get install -sf"); + } + { + const char* const argv[] = {"apt-cache", "-s", "apt", "-so", "Debug::test=Test"}; + CMD(5, "apt-cache -s apt -so Debug::test=Test"); + } + { + const char* const argv[] = {"apt-cache", "-s", "apt", "-so", "Debug::test=Das ist ein Test"}; + CMD(5, "apt-cache -s apt -so Debug::test=\"Das ist ein Test\""); + } + { + const char* const argv[] = {"apt-cache", "-s", "apt", "--hallo", "test=1.0"}; + CMD(5, "apt-cache -s apt --hallo test=1.0"); + } +} diff --git a/test/libapt/makefile b/test/libapt/makefile index 08f581e6d..cb76d5ee6 100644 --- a/test/libapt/makefile +++ b/test/libapt/makefile @@ -23,3 +23,9 @@ PROGRAM = GetListOfFilesInDir${BASENAME} SLIBS = -lapt-pkg SOURCE = getlistoffilesindir_test.cc include $(PROGRAM_H) + +# Program for testing CommandLine reconstruction +PROGRAM = commandlineasstring${BASENAME} +SLIBS = -lapt-pkg +SOURCE = commandlineasstring_test.cc +include $(PROGRAM_H) -- cgit v1.2.3-70-g09d2 From 6dc60370a750334cb701386cfa4ef9719db9078a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 30 Mar 2010 12:38:38 +0200 Subject: replace every call to toupper with one to our own tolower_ascii This sounds like a premature optimization and since Mr. Knuth we all know that they are the root of all evil - but, and here it starts to be interesting: As the tolower_ascii method is by far the most called method we have (~60 Mio. times) and as we compare only strings containing ascii characters (package names, configuration options) using our own method reduces execution time of APT by 4% plus it avoids that the locale settings can influence us. --- apt-pkg/contrib/error.h | 8 ++++---- apt-pkg/contrib/macros.h | 10 ++++++---- apt-pkg/contrib/strutl.cc | 49 +++++++++++++++++++++++++---------------------- apt-pkg/contrib/strutl.h | 21 ++++++-------------- debian/changelog | 2 ++ 5 files changed, 44 insertions(+), 46 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index 90747ff7e..8d5ec05ea 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -60,13 +60,13 @@ class GlobalError public: // Call to generate an error from a library call. - bool Errno(const char *Function,const char *Description,...) __like_printf_2 __cold; - bool WarningE(const char *Function,const char *Description,...) __like_printf_2 __cold; + bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold; + bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold; /* A warning should be considered less severe than an error, and may be ignored by the client. */ - bool Error(const char *Description,...) __like_printf_1 __cold; - bool Warning(const char *Description,...) __like_printf_1 __cold; + bool Error(const char *Description,...) __like_printf(2) __cold; + bool Warning(const char *Description,...) __like_printf(2) __cold; // Simple accessors inline bool PendingError() {return PendingFlag;}; diff --git a/apt-pkg/contrib/macros.h b/apt-pkg/contrib/macros.h index c39caf198..62e7b65db 100644 --- a/apt-pkg/contrib/macros.h +++ b/apt-pkg/contrib/macros.h @@ -58,6 +58,7 @@ #if __GNUC__ >= 3 #define __must_check __attribute__ ((warn_unused_result)) #define __deprecated __attribute__ ((deprecated)) + #define __attrib_const __attribute__ ((__const__)) /* likely() and unlikely() can be used to mark boolean expressions as (not) likely true which will help the compiler to optimise */ #define likely(x) __builtin_expect (!!(x), 1) @@ -65,6 +66,7 @@ #else #define __must_check /* no warn_unused_result */ #define __deprecated /* no deprecated */ + #define __attrib_const /* no const attribute */ #define likely(x) (x) #define unlikely(x) (x) #endif @@ -72,17 +74,17 @@ // cold functions are unlikely() to be called #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4 #define __cold __attribute__ ((__cold__)) + #define __hot __attribute__ ((__hot__)) #else #define __cold /* no cold marker */ + #define __hot /* no hot marker */ #endif #ifdef __GNUG__ // Methods have a hidden this parameter that is visible to this attribute - #define __like_printf_1 __attribute__ ((format (printf, 2, 3))) - #define __like_printf_2 __attribute__ ((format (printf, 3, 4))) + #define __like_printf(n) __attribute__((format(printf, n, n + 1))) #else - #define __like_printf_1 /* no like-printf */ - #define __like_printf_2 /* no like-printf */ + #define __like_printf(n) /* no like-printf */ #endif #endif diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 1b9922a31..ab47cdede 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -566,7 +566,7 @@ int stringcmp(string::const_iterator A,string::const_iterator AEnd, int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd) { for (; A != AEnd && B != BEnd; A++, B++) - if (toupper(*A) != toupper(*B)) + if (tolower_ascii(*A) != tolower_ascii(*B)) break; if (A == AEnd && B == BEnd) @@ -575,7 +575,7 @@ int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd) return 1; if (B == BEnd) return -1; - if (toupper(*A) < toupper(*B)) + if (tolower_ascii(*A) < tolower_ascii(*B)) return -1; return 1; } @@ -584,7 +584,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd, const char *B,const char *BEnd) { for (; A != AEnd && B != BEnd; A++, B++) - if (toupper(*A) != toupper(*B)) + if (tolower_ascii(*A) != tolower_ascii(*B)) break; if (A == AEnd && B == BEnd) @@ -593,7 +593,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd, return 1; if (B == BEnd) return -1; - if (toupper(*A) < toupper(*B)) + if (tolower_ascii(*A) < tolower_ascii(*B)) return -1; return 1; } @@ -601,7 +601,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd, string::const_iterator B,string::const_iterator BEnd) { for (; A != AEnd && B != BEnd; A++, B++) - if (toupper(*A) != toupper(*B)) + if (tolower_ascii(*A) != tolower_ascii(*B)) break; if (A == AEnd && B == BEnd) @@ -610,7 +610,7 @@ int stringcasecmp(string::const_iterator A,string::const_iterator AEnd, return 1; if (B == BEnd) return -1; - if (toupper(*A) < toupper(*B)) + if (tolower_ascii(*A) < tolower_ascii(*B)) return -1; return 1; } @@ -789,28 +789,28 @@ bool ReadMessages(int Fd, vector &List) // MonthConv - Converts a month string into a number /*{{{*/ // --------------------------------------------------------------------- /* This was lifted from the boa webserver which lifted it from 'wn-v1.07' - Made it a bit more robust with a few touppers though. */ + Made it a bit more robust with a few tolower_ascii though. */ static int MonthConv(char *Month) { - switch (toupper(*Month)) + switch (tolower_ascii(*Month)) { - case 'A': - return toupper(Month[1]) == 'P'?3:7; - case 'D': + case 'a': + return tolower_ascii(Month[1]) == 'p'?3:7; + case 'd': return 11; - case 'F': + case 'f': return 1; - case 'J': - if (toupper(Month[1]) == 'A') + case 'j': + if (tolower_ascii(Month[1]) == 'a') return 0; - return toupper(Month[2]) == 'N'?5:6; - case 'M': - return toupper(Month[2]) == 'R'?2:4; - case 'N': + return tolower_ascii(Month[2]) == 'n'?5:6; + case 'm': + return tolower_ascii(Month[2]) == 'r'?2:4; + case 'n': return 10; - case 'O': + case 'o': return 9; - case 'S': + case 's': return 8; // Pretend it is January.. @@ -1133,10 +1133,13 @@ char *safe_snprintf(char *Buffer,char *End,const char *Format,...) // tolower_ascii - tolower() function that ignores the locale /*{{{*/ // --------------------------------------------------------------------- -/* */ -int tolower_ascii(int c) +/* This little function is the most called method we have and tries + therefore to do the absolut minimum - and is noteable faster than + standard tolower/toupper and as a bonus avoids problems with different + locales - we only operate on ascii chars anyway. */ +int tolower_ascii(int const c) { - if (c >= 'A' and c <= 'Z') + if (c >= 'A' && c <= 'Z') return c + 32; return c; } diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index e72288f4c..cdf78f317 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -25,19 +25,12 @@ #include #include +#include "macros.h" + using std::string; using std::vector; using std::ostream; -#ifdef __GNUG__ -// Methods have a hidden this parameter that is visible to this attribute -#define APT_FORMAT2 __attribute__ ((format (printf, 2, 3))) -#define APT_FORMAT3 __attribute__ ((format (printf, 3, 4))) -#else -#define APT_FORMAT2 -#define APT_FORMAT3 -#endif - bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest); char *_strstrip(char *String); char *_strtabexpand(char *String,size_t Len); @@ -60,11 +53,11 @@ bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length); bool TokSplitString(char Tok,char *Input,char **List, unsigned long ListMax); vector ExplodeString(string const &haystack, char const &split); -void ioprintf(ostream &out,const char *format,...) APT_FORMAT2; -void strprintf(string &out,const char *format,...) APT_FORMAT2; -char *safe_snprintf(char *Buffer,char *End,const char *Format,...) APT_FORMAT3; +void ioprintf(ostream &out,const char *format,...) __like_printf(2); +void strprintf(string &out,const char *format,...) __like_printf(2); +char *safe_snprintf(char *Buffer,char *End,const char *Format,...) __like_printf(3); bool CheckDomainList(const string &Host, const string &List); -int tolower_ascii(int c); +int tolower_ascii(int const c) __attrib_const __hot; #define APT_MKSTRCMP(name,func) \ inline int name(const char *A,const char *B) {return func(A,A+strlen(A),B,B+strlen(B));}; \ @@ -144,6 +137,4 @@ struct RxChoiceList unsigned long RegexChoice(RxChoiceList *Rxs,const char **ListBegin, const char **ListEnd); -#undef APT_FORMAT2 - #endif diff --git a/debian/changelog b/debian/changelog index 17affee4f..bd1fda316 100644 --- a/debian/changelog +++ b/debian/changelog @@ -60,6 +60,8 @@ apt (0.7.26) UNRELEASED; urgency=low * doc/po/de.po: - correct a few typos in the german manpage translation. Thanks to Chris Leick and Georg Koppen! (Closes: #574962) + * apt-pkg/contrib/strutl.cc: + - convert all toupper calls to tolower_ascii for a little speedup [ Julian Andres Klode ] * cmdline/apt-mark: -- cgit v1.2.3-70-g09d2 From 3f42500d6b9eb318c46cacafdcfd6beb707ef9e9 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 30 Mar 2010 14:25:57 +0200 Subject: rename ExplodeString to VectorizeString --- apt-pkg/aptconfiguration.cc | 2 +- apt-pkg/contrib/strutl.cc | 6 +++--- apt-pkg/contrib/strutl.h | 2 +- apt-pkg/deb/debmetaindex.cc | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index a1379ce7d..2acf8dd9f 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -221,7 +221,7 @@ std::vector const Configuration::getLanguages(bool const &All, const char *language_env = getenv("LANGUAGE") == 0 ? "" : getenv("LANGUAGE"); string envLang = Locale == 0 ? language_env : *(Locale+1); if (envLang.empty() == false) { - std::vector env = ExplodeString(envLang,':'); + std::vector env = VectorizeString(envLang,':'); short addedLangs = 0; // add a maximum of 3 fallbacks from the environment for (std::vector::const_iterator e = env.begin(); e != env.end() && addedLangs < 3; ++e) { diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index ab47cdede..7eb986ac0 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1000,12 +1000,12 @@ bool TokSplitString(char Tok,char *Input,char **List, return true; } /*}}}*/ -// ExplodeString - Split a string up into a vector /*{{{*/ +// VectorizeString - Split a string up into a vector of strings /*{{{*/ // --------------------------------------------------------------------- /* This can be used to split a given string up into a vector, so the propose is the same as in the method above and this one is a bit slower - also, but the advantage is that we an iteratable vector */ -vector ExplodeString(string const &haystack, char const &split) + also, but the advantage is that we have an iteratable vector */ +vector VectorizeString(string const &haystack, char const &split) { string::const_iterator start = haystack.begin(); string::const_iterator end = start; diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index cdf78f317..d8070d3f5 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -52,7 +52,7 @@ bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0) bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length); bool TokSplitString(char Tok,char *Input,char **List, unsigned long ListMax); -vector ExplodeString(string const &haystack, char const &split); +vector VectorizeString(string const &haystack, char const &split) __attrib_const; void ioprintf(ostream &out,const char *format,...) __like_printf(2); void strprintf(string &out,const char *format,...) __like_printf(2); char *safe_snprintf(char *Buffer,char *End,const char *Format,...) __like_printf(3); diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 947a7f04b..8df3ed18d 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -313,7 +313,7 @@ class debSLTypeDebian : public pkgSourceList::Type { map::const_iterator const arch = Options.find("arch"); vector const Archs = - (arch != Options.end()) ? ExplodeString(arch->second, ',') : + (arch != Options.end()) ? VectorizeString(arch->second, ',') : APT::Configuration::getArchitectures(); for (vector::const_iterator I = List.begin(); -- cgit v1.2.3-70-g09d2 From 436d7eab92bb8f9cc6498acfbf2055e717be6fd0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 31 Mar 2010 17:19:10 +0200 Subject: Userinfo is urlencoded in URIs (RFC 3986) Thanks to Jean-Baptiste Lallement for spotting and fixing it! * apt-pkg/contrib/strutl.cc: - always escape '%' (LP: #130289) (Closes: #500560) - unescape '%' sequence only if followed by 2 hex digit - username/password are urlencoded in proxy string (RFC 3986) --- apt-pkg/contrib/strutl.cc | 21 +++++++++++++++------ apt-pkg/contrib/strutl.h | 1 + debian/changelog | 6 ++++++ 3 files changed, 22 insertions(+), 6 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 7eb986ac0..c7d63ce8a 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -198,7 +198,8 @@ bool ParseQuoteWord(const char *&String,string &Res) char *I; for (I = Buffer; I < Buffer + sizeof(Buffer) && Start != C; I++) { - if (*Start == '%' && Start + 2 < C) + if (*Start == '%' && Start + 2 < C && + isxdigit(Start[1]) && isxdigit(Start[2])) { Tmp[0] = Start[1]; Tmp[1] = Start[2]; @@ -273,7 +274,8 @@ string QuoteString(const string &Str, const char *Bad) for (string::const_iterator I = Str.begin(); I != Str.end(); I++) { if (strchr(Bad,*I) != 0 || isprint(*I) == 0 || - *I <= 0x20 || *I >= 0x7F) + *I == 0x25 || // percent '%' char + *I <= 0x20 || *I >= 0x7F) // control chars { char Buf[10]; sprintf(Buf,"%%%02x",(int)*I); @@ -289,11 +291,17 @@ string QuoteString(const string &Str, const char *Bad) // --------------------------------------------------------------------- /* This undoes QuoteString */ string DeQuoteString(const string &Str) +{ + return DeQuoteString(Str.begin(),Str.end()); +} +string DeQuoteString(string::const_iterator const &begin, + string::const_iterator const &end) { string Res; - for (string::const_iterator I = Str.begin(); I != Str.end(); I++) + for (string::const_iterator I = begin; I != end; I++) { - if (*I == '%' && I + 2 < Str.end()) + if (*I == '%' && I + 2 < end && + isxdigit(I[1]) && isxdigit(I[2])) { char Tmp[3]; Tmp[0] = I[1]; @@ -1238,9 +1246,10 @@ void URI::CopyFrom(const string &U) else { Host.assign(At+1,SingleSlash); - User.assign(FirstColon,SecondColon); + // username and password must be encoded (RFC 3986) + User.assign(DeQuoteString(FirstColon,SecondColon)); if (SecondColon < At) - Password.assign(SecondColon+1,At); + Password.assign(DeQuoteString(SecondColon+1,At)); } // Now we parse the RFC 2732 [] hostnames. diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index d8070d3f5..e509145f9 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -38,6 +38,7 @@ bool ParseQuoteWord(const char *&String,string &Res); bool ParseCWord(const char *&String,string &Res); string QuoteString(const string &Str,const char *Bad); string DeQuoteString(const string &Str); +string DeQuoteString(string::const_iterator const &begin, string::const_iterator const &end); string SizeToStr(double Bytes); string TimeToStr(unsigned long Sec); string Base64Encode(const string &Str); diff --git a/debian/changelog b/debian/changelog index 61a4dc618..205db85e0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -64,6 +64,12 @@ apt (0.7.26) UNRELEASED; urgency=low * apt-pkg/contrib/strutl.cc: - convert all toupper calls to tolower_ascii for a little speedup + [ Jean-Baptiste Lallement ] + * apt-pkg/contrib/strutl.cc: + - always escape '%' (LP: #130289) (Closes: #500560) + - unescape '%' sequence only if followed by 2 hex digit + - username/password are urlencoded in proxy string (RFC 3986) + [ Julian Andres Klode ] * cmdline/apt-mark: - Use the new python-apt API (and conflict with python-apt << 0.7.93.2). -- cgit v1.2.3-70-g09d2 From b3793d41d420a895ef5be4521a56535cc79f0d4a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 4 Apr 2010 10:34:45 +0200 Subject: remove the ABI compatible stub for GetListOfFilesInDir --- apt-pkg/contrib/fileutl.cc | 5 ----- apt-pkg/contrib/fileutl.h | 5 +---- 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index da32983f1..75adce305 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -201,11 +201,6 @@ bool FileExists(string File) // --------------------------------------------------------------------- /* If an extension is given only files with this extension are included in the returned vector, otherwise every "normal" file is included. */ -std::vector GetListOfFilesInDir(string const &Dir, string const &Ext, - bool const &SortList) -{ - return GetListOfFilesInDir(Dir, Ext, SortList, false); -} std::vector GetListOfFilesInDir(string const &Dir, string const &Ext, bool const &SortList, bool const &AllowNoExt) { diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 85a94898c..351d53c5e 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -82,11 +82,8 @@ bool RunScripts(const char *Cnf); bool CopyFile(FileFd &From,FileFd &To); int GetLock(string File,bool Errors = true); bool FileExists(string File); -// FIXME: next ABI-Break: merge the two method-headers std::vector GetListOfFilesInDir(string const &Dir, string const &Ext, - bool const &SortList); -std::vector GetListOfFilesInDir(string const &Dir, string const &Ext, - bool const &SortList, bool const &AllowNoExt); + bool const &SortList, bool const &AllowNoExt=false); std::vector GetListOfFilesInDir(string const &Dir, std::vector const &Ext, bool const &SortList); string SafeGetCWD(); -- cgit v1.2.3-70-g09d2 From 1cd1c398d18b78f4aa9d882a5de5385f4538e0be Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 7 Apr 2010 16:38:18 +0200 Subject: * apt-pkg/contrib/fileutl.cc: - add a parent-guarded "mkdir -p" as CreateDirectory() * apt-pkg/acquire.{cc,h}: - add a delayed constructor with Setup() for success reporting - check for and create directories in Setup if needed instead of error out unfriendly in the Constructor (Closes: #523920, #525783) - optional handle a lock file in Setup() * cmdline/apt-get.cc: - remove the lock file handling and let Acquire take care of it instead --- apt-pkg/acquire.cc | 89 ++++++++++++++++++++++++++++++++++------------ apt-pkg/acquire.h | 31 +++++++++++++--- apt-pkg/algorithms.cc | 4 ++- apt-pkg/contrib/fileutl.cc | 52 +++++++++++++++++++++++++++ apt-pkg/contrib/fileutl.h | 3 ++ apt-pkg/pkgcachegen.cc | 15 +++++++- cmdline/apt-get.cc | 38 ++++++++------------ debian/changelog | 9 +++++ 8 files changed, 187 insertions(+), 54 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 74510ae21..d83d80fac 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -29,7 +30,6 @@ #include #include #include -#include /*}}}*/ using namespace std; @@ -37,32 +37,72 @@ using namespace std; // Acquire::pkgAcquire - Constructor /*{{{*/ // --------------------------------------------------------------------- /* We grab some runtime state from the configuration space */ -pkgAcquire::pkgAcquire(pkgAcquireStatus *Log) : Log(Log) +pkgAcquire::pkgAcquire() : Queues(0), Workers(0), Configs(0), Log(NULL), ToFetch(0), + Debug(_config->FindB("Debug::pkgAcquire",false)), + Running(false), LockFD(-1) { - Queues = 0; - Configs = 0; - Workers = 0; - ToFetch = 0; - Running = false; - - string Mode = _config->Find("Acquire::Queue-Mode","host"); + string const Mode = _config->Find("Acquire::Queue-Mode","host"); + if (strcasecmp(Mode.c_str(),"host") == 0) + QueueMode = QueueHost; + if (strcasecmp(Mode.c_str(),"access") == 0) + QueueMode = QueueAccess; +} +pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) : Queues(0), Workers(0), + Configs(0), Log(Progress), ToFetch(0), + Debug(_config->FindB("Debug::pkgAcquire",false)), + Running(false), LockFD(-1) +{ + string const Mode = _config->Find("Acquire::Queue-Mode","host"); if (strcasecmp(Mode.c_str(),"host") == 0) QueueMode = QueueHost; if (strcasecmp(Mode.c_str(),"access") == 0) - QueueMode = QueueAccess; + QueueMode = QueueAccess; + Setup(Progress, ""); +} + /*}}}*/ +// Acquire::Setup - Delayed Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* Do everything needed to be a complete Acquire object and report the + success (or failure) back so the user knows that something is wrong… */ +bool pkgAcquire::Setup(pkgAcquireStatus *Progress, string const &Lock) +{ + Log = Progress; - Debug = _config->FindB("Debug::pkgAcquire",false); - - // This is really a stupid place for this - struct stat St; - if (stat((_config->FindDir("Dir::State::lists") + "partial/").c_str(),&St) != 0 || - S_ISDIR(St.st_mode) == 0) - _error->Error(_("Lists directory %spartial is missing."), - _config->FindDir("Dir::State::lists").c_str()); - if (stat((_config->FindDir("Dir::Cache::Archives") + "partial/").c_str(),&St) != 0 || - S_ISDIR(St.st_mode) == 0) - _error->Error(_("Archive directory %spartial is missing."), - _config->FindDir("Dir::Cache::Archives").c_str()); + // check for existence and possibly create auxiliary directories + if (CheckDirectory(_config->FindDir("Dir::State"), _config->FindDir("Dir::State::lists") + "partial/") == false || + CheckDirectory(_config->FindDir("Dir::Cache"), _config->FindDir("Dir::Cache::Archives") + "partial/") == false) + return false; + + if (Lock.empty() == true || _config->FindB("Debug::NoLocking", false) == true) + return true; + + // Lock the directory this acquire object will work in + LockFD = GetLock(flCombine(Lock, "lock")); + if (LockFD == -1) + return _error->Error(_("Unable to lock directory %s"), Lock.c_str()); + + return true; +} + /*}}}*/ +// Acquire::CheckDirectory - ensure that the given directory exists /*{{{*/ +// --------------------------------------------------------------------- +/* a small wrapper around CreateDirectory to check if it exists and to + remove the trailing "/apt/" from the parent directory if needed */ +bool pkgAcquire::CheckDirectory(string const &Parent, string const &Path) const +{ + if (DirectoryExists(Path) == true) + return true; + + size_t const len = Parent.size(); + if (len > 5 && Parent.find("/apt/", len - 6, 5) != len - 5) + { + if (CreateDirectory(Parent.substr(0,len-5), Path) == true) + return true; + } + else if (CreateDirectory(Parent, Path) == true) + return true; + + return _error->Errno("Acquire", _("Directory %s can't be created."), Path.c_str()); } /*}}}*/ // Acquire::~pkgAcquire - Destructor /*{{{*/ @@ -71,7 +111,10 @@ pkgAcquire::pkgAcquire(pkgAcquireStatus *Log) : Log(Log) pkgAcquire::~pkgAcquire() { Shutdown(); - + + if (LockFD != -1) + close(LockFD); + while (Configs != 0) { MethodConfig *Jnk = Configs; diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h index 6c130c1b3..9e91a9f67 100644 --- a/apt-pkg/acquire.h +++ b/apt-pkg/acquire.h @@ -66,6 +66,8 @@ #ifndef PKGLIB_ACQUIRE_H #define PKGLIB_ACQUIRE_H +#include + #include #include @@ -161,7 +163,7 @@ class pkgAcquire QueueAccess} QueueMode; /** \brief If \b true, debugging information will be dumped to std::clog. */ - bool Debug; + bool const Debug; /** \brief If \b true, a download is currently in progress. */ bool Running; @@ -332,15 +334,22 @@ class pkgAcquire */ double PartialPresent(); - /** \brief Construct a new pkgAcquire. + /** \brief Delayed constructor * - * \param Log The progress indicator associated with this - * download, or \b NULL for none. This object is not owned by the + * \param Progress indicator associated with this download or + * \b NULL for none. This object is not owned by the * download process and will not be deleted when the pkgAcquire * object is destroyed. Naturally, it should live for at least as * long as the pkgAcquire object does. + * \param Lock defines a lock file that should be acquired to ensure + * only one Acquire class is in action at the time or an empty string + * if no lock file should be used. */ - pkgAcquire(pkgAcquireStatus *Log = 0); + bool Setup(pkgAcquireStatus *Progress = NULL, string const &Lock = ""); + + /** \brief Construct a new pkgAcquire. */ + pkgAcquire(pkgAcquireStatus *Log) __deprecated; + pkgAcquire(); /** \brief Destroy this pkgAcquire object. * @@ -348,6 +357,18 @@ class pkgAcquire * this download. */ virtual ~pkgAcquire(); + + private: + /** \brief FD of the Lock file we acquire in Setup (if any) */ + int LockFD; + + /** \brief Ensure the existence of the given Path + * + * \param Parent directory of the Path directory - a trailing + * /apt/ will be removed before CreateDirectory call. + * \param Path which should exist after (successful) call + */ + bool CheckDirectory(string const &Parent, string const &Path) const; }; /** \brief Represents a single download source from which an item diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index f8a9e210c..f1e51131a 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -1398,7 +1398,9 @@ bool ListUpdate(pkgAcquireStatus &Stat, int PulseInterval) { pkgAcquire::RunResult res; - pkgAcquire Fetcher(&Stat); + pkgAcquire Fetcher; + if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false) + return false; // Populate it with the source selection if (List.GetIndexes(&Fetcher) == false) diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 75adce305..16f7ce929 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -18,6 +18,7 @@ /*}}}*/ // Include Files /*{{{*/ #include +#include #include #include #include @@ -197,6 +198,57 @@ bool FileExists(string File) return true; } /*}}}*/ +// DirectoryExists - Check if a directory exists and is really one /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool DirectoryExists(string const &Path) +{ + struct stat Buf; + if (stat(Path.c_str(),&Buf) != 0) + return false; + return ((Buf.st_mode & S_IFDIR) != 0); +} + /*}}}*/ +// CreateDirectory - poor man's mkdir -p guarded by a parent directory /*{{{*/ +// --------------------------------------------------------------------- +/* This method will create all directories needed for path in good old + mkdir -p style but refuses to do this if Parent is not a prefix of + this Path. Example: /var/cache/ and /var/cache/apt/archives are given, + so it will create apt/archives if /var/cache exists - on the other + hand if the parent is /var/lib the creation will fail as this path + is not a parent of the path to be generated. */ +bool CreateDirectory(string const &Parent, string const &Path) +{ + if (Parent.empty() == true || Path.empty() == true) + return false; + + if (DirectoryExists(Path) == true) + return true; + + if (DirectoryExists(Parent) == false) + return false; + + // we are not going to create directories "into the blue" + if (Path.find(Parent, 0) != 0) + return false; + + vector const dirs = VectorizeString(Path.substr(Parent.size()), '/'); + string progress = Parent; + for (vector::const_iterator d = dirs.begin(); d != dirs.end(); ++d) + { + if (d->empty() == true) + continue; + + progress.append("/").append(*d); + if (DirectoryExists(progress) == true) + continue; + + if (mkdir(progress.c_str(), 0755) != 0) + return false; + } + return true; +} + /*}}}*/ // GetListOfFilesInDir - returns a vector of files in the given dir /*{{{*/ // --------------------------------------------------------------------- /* If an extension is given only files with this extension are included diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 351d53c5e..003bd9b83 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -21,6 +21,7 @@ #ifndef PKGLIB_FILEUTL_H #define PKGLIB_FILEUTL_H +#include #include #include @@ -82,6 +83,8 @@ bool RunScripts(const char *Cnf); bool CopyFile(FileFd &From,FileFd &To); int GetLock(string File,bool Errors = true); bool FileExists(string File); +bool DirectoryExists(string const &Path) __attrib_const; +bool CreateDirectory(string const &Parent, string const &Path); std::vector GetListOfFilesInDir(string const &Dir, string const &Ext, bool const &SortList, bool const &AllowNoExt=false); std::vector GetListOfFilesInDir(string const &Dir, std::vector const &Ext, diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 21240b951..114c9d5ed 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -1003,7 +1003,20 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress, // Decide if we can write to the files.. string const CacheFile = _config->FindFile("Dir::Cache::pkgcache"); string const SrcCacheFile = _config->FindFile("Dir::Cache::srcpkgcache"); - + + // ensure the cache directory exists + if (CacheFile.empty() == false || SrcCacheFile.empty() == false) + { + string dir = _config->FindDir("Dir::Cache"); + size_t const len = dir.size(); + if (len > 5 && dir.find("/apt/", len - 6, 5) == len - 5) + dir = dir.substr(0, len - 5); + if (CacheFile.empty() == false) + CreateDirectory(dir, flNotFile(CacheFile)); + if (SrcCacheFile.empty() == false) + CreateDirectory(dir, flNotFile(SrcCacheFile)); + } + // Decide if we can write to the cache bool Writeable = false; if (CacheFile.empty() == false) diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 62f712c39..416d316da 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -811,20 +811,13 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, pkgRecords Recs(Cache); if (_error->PendingError() == true) return false; - - // Lock the archive directory - FileFd Lock; - if (_config->FindB("Debug::NoLocking",false) == false && - _config->FindB("APT::Get::Print-URIs") == false) - { - Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock")); - if (_error->PendingError() == true) - return _error->Error(_("Unable to lock the download directory")); - } - + // Create the download object + pkgAcquire Fetcher; AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - pkgAcquire Fetcher(&Stat); + if (Fetcher.Setup(&Stat, _config->FindB("APT::Get::Print-URIs", false) + ? "" : _config->FindDir("Dir::Cache::Archives")) == false) + return false; // Read the source list pkgSourceList List; @@ -1442,15 +1435,6 @@ bool DoUpdate(CommandLine &CmdL) if (List.ReadMainList() == false) return false; - // Lock the list directory - FileFd Lock; - if (_config->FindB("Debug::NoLocking",false) == false) - { - Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock")); - if (_error->PendingError() == true) - return _error->Error(_("Unable to lock the list directory")); - } - // Create the progress AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); @@ -1458,7 +1442,9 @@ bool DoUpdate(CommandLine &CmdL) if (_config->FindB("APT::Get::Print-URIs") == true) { // get a fetcher - pkgAcquire Fetcher(&Stat); + pkgAcquire Fetcher; + if (Fetcher.Setup(&Stat) == false) + return false; // Populate it with the source selection and get all Indexes // (GetAll=true) @@ -2207,7 +2193,9 @@ bool DoSource(CommandLine &CmdL) // Create the download object AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - pkgAcquire Fetcher(&Stat); + pkgAcquire Fetcher; + if (Fetcher.Setup(&Stat) == false) + return false; DscFile *Dsc = new DscFile[CmdL.FileSize()]; @@ -2464,7 +2452,9 @@ bool DoBuildDep(CommandLine &CmdL) // Create the download object AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - pkgAcquire Fetcher(&Stat); + pkgAcquire Fetcher; + if (Fetcher.Setup(&Stat) == false) + return false; unsigned J = 0; for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) diff --git a/debian/changelog b/debian/changelog index 71aeb1504..ffab08eb1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,15 @@ apt (0.7.26~exp4) experimental; urgency=low - "reinstall" the correct version for a killed pseudo package * apt-pkg/packagemanager.cc: - don't try to "unpack" pseudo packages twice + * apt-pkg/contrib/fileutl.cc: + - add a parent-guarded "mkdir -p" as CreateDirectory() + * apt-pkg/acquire.{cc,h}: + - add a delayed constructor with Setup() for success reporting + - check for and create directories in Setup if needed instead of + error out unfriendly in the Constructor (Closes: #523920, #525783) + - optional handle a lock file in Setup() + * cmdline/apt-get.cc: + - remove the lock file handling and let Acquire take care of it instead -- David Kalnischkies Sat, 03 Apr 2010 14:58:39 +0200 -- cgit v1.2.3-70-g09d2 From c3a3a1b1b68706df40dc022bdcdf8ede684f5956 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 24 Apr 2010 12:44:11 +0200 Subject: * apt-pkg/contrib/configuration.cc: - error out if #clear directive has no argument --- apt-pkg/contrib/configuration.cc | 2 ++ debian/changelog | 2 ++ 2 files changed, 4 insertions(+) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 7588b041c..9129d92f0 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -773,6 +773,8 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio else return _error->Error(_("Syntax error %s:%u: Unsupported directive '%s'"),FName.c_str(),CurLine,Tag.c_str()); } + else if (Tag.empty() == true && NoWord == false && Word == "#clear") + return _error->Error(_("Syntax error %s:%u: clear directive requires an option tree as argument"),FName.c_str(),CurLine); else { // Set the item in the configuration class diff --git a/debian/changelog b/debian/changelog index f78f80936..ee2be291b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -34,6 +34,8 @@ apt (0.7.26~exp4) experimental; urgency=low - correct typos in german apt_preferences manpage, thanks Chris Leick! * apt-pkg/sourcelist.cc: - be less strict and accept [option=value] as well + * apt-pkg/contrib/configuration.cc: + - error out if #clear directive has no argument [ Jari Aalto ] * cmdline/apt-get.cc: -- cgit v1.2.3-70-g09d2 From 229fb1a3a35bade26cfff373087461d7a98aade3 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 4 May 2010 17:05:23 +0200 Subject: * apt-pkg/contrib/weakptr.h: - add a class WeakPointable which allows one to register weak pointers to an object which will be set to NULL when the object is deallocated. * [ABI break] apt-pkg/acquire{-worker,-item,}.h: - subclass pkgAcquire::{Worker,Item,ItemDesc} from WeakPointable. --- apt-pkg/acquire-item.h | 3 ++- apt-pkg/acquire-worker.h | 3 ++- apt-pkg/acquire.h | 3 ++- apt-pkg/contrib/weakptr.h | 62 +++++++++++++++++++++++++++++++++++++++++++++++ apt-pkg/makefile | 2 +- debian/changelog | 7 ++++++ 6 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 apt-pkg/contrib/weakptr.h (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index bafa8263a..b338b2a41 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -27,6 +27,7 @@ #include #include #include +#include /** \addtogroup acquire * @{ @@ -46,7 +47,7 @@ * * \see pkgAcquire */ -class pkgAcquire::Item +class pkgAcquire::Item : public WeakPointable { protected: diff --git a/apt-pkg/acquire-worker.h b/apt-pkg/acquire-worker.h index 2942df69f..06283922e 100644 --- a/apt-pkg/acquire-worker.h +++ b/apt-pkg/acquire-worker.h @@ -20,6 +20,7 @@ #define PKGLIB_ACQUIRE_WORKER_H #include +#include /** \brief A fetch subprocess. @@ -41,7 +42,7 @@ * * \sa pkgAcqMethod, pkgAcquire::Item, pkgAcquire */ -class pkgAcquire::Worker +class pkgAcquire::Worker : public WeakPointable { friend class pkgAcquire; diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h index 9e91a9f67..8e2c21151 100644 --- a/apt-pkg/acquire.h +++ b/apt-pkg/acquire.h @@ -67,6 +67,7 @@ #define PKGLIB_ACQUIRE_H #include +#include #include #include @@ -376,7 +377,7 @@ class pkgAcquire * * An item may have several assocated ItemDescs over its lifetime. */ -struct pkgAcquire::ItemDesc +struct pkgAcquire::ItemDesc : public WeakPointable { /** \brief The URI from which to download this item. */ string URI; diff --git a/apt-pkg/contrib/weakptr.h b/apt-pkg/contrib/weakptr.h new file mode 100644 index 000000000..5158e393c --- /dev/null +++ b/apt-pkg/contrib/weakptr.h @@ -0,0 +1,62 @@ +/* weakptr.h - An object which supports weak pointers. + * + * Copyright (C) 2010 Julian Andres Klode + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef WEAK_POINTER_H +#define WEAK_POINTER_H + +#include +/** + * Class for objects providing support for weak pointers. + * + * This class allows for the registration of certain pointers as weak, + * which will cause them to be set to NULL when the destructor of the + * object is called. + */ +class WeakPointable { +private: + std::set pointers; + +public: + + /** + * Add a new weak pointer. + */ + inline void AddWeakPointer(WeakPointable** weakptr) { + pointers.insert(weakptr); + } + + /** + * Remove the weak pointer from the list of weak pointers. + */ + inline void RemoveWeakPointer(WeakPointable **weakptr) { + pointers.erase(weakptr); + } + + /** + * Deconstruct the object, set all weak pointers to NULL. + */ + ~WeakPointable() { + std::set::iterator iter = pointers.begin(); + while (iter != pointers.end()) + **(iter++) = NULL; + } +}; + +#endif // WEAK_POINTER_H diff --git a/apt-pkg/makefile b/apt-pkg/makefile index bdd49c089..148ad581b 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -25,7 +25,7 @@ SOURCE = contrib/mmap.cc contrib/error.cc contrib/strutl.cc \ contrib/fileutl.cc HEADERS = mmap.h error.h configuration.h fileutl.h cmndline.h netrc.h\ md5.h crc-16.h cdromutl.h strutl.h sptr.h sha1.h sha256.h hashes.h \ - macros.h + macros.h weakptr.h # Source code for the core main library SOURCE+= pkgcache.cc version.cc depcache.cc \ diff --git a/debian/changelog b/debian/changelog index 97e15326c..b316f9548 100644 --- a/debian/changelog +++ b/debian/changelog @@ -59,6 +59,13 @@ apt (0.7.26~exp4) UNRELEASEDexperimental; urgency=low - Add test for Esperanto that has nocounty associated with them (LP: #560956) + [ Julian Andres Klode ] + * apt-pkg/contrib/weakptr.h: + - add a class WeakPointable which allows one to register weak pointers to + an object which will be set to NULL when the object is deallocated. + * [ABI break] apt-pkg/acquire{-worker,-item,}.h: + - subclass pkgAcquire::{Worker,Item,ItemDesc} from WeakPointable. + -- David Kalnischkies Sat, 03 Apr 2010 14:58:39 +0200 apt (0.7.26~exp3) experimental; urgency=low -- cgit v1.2.3-70-g09d2 From e3ac3b464d4b084c524076c7e2ab2c737ccdb99c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 13 May 2010 15:20:07 +0200 Subject: * contrib/mmap.cc: - clarify "MMap reached size limit" error message, thanks Ivan Masár! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apt-pkg/contrib/mmap.cc | 4 ++-- debian/changelog | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index b3f29032c..d233e51bc 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -392,8 +392,8 @@ unsigned long DynamicMMap::WriteString(const char *String, the nearly impossible 4 to grow it before it finally give up: Never say never. */ bool DynamicMMap::Grow() { if (Limit != 0 && WorkSpace >= Limit) - return _error->Error(_("The size of a MMap has already reached the defined limit of %lu bytes," - "abort the try to grow the MMap."), Limit); + return _error->Error(_("Unable to increase the size of the MMap as the " + "limit of %lu bytes is already reached."), Limit); unsigned long const newSize = WorkSpace + 1024*1024; diff --git a/debian/changelog b/debian/changelog index a328c1e1e..8a6424ebc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,15 +10,17 @@ apt (0.7.26~exp5) UNRELEASED; urgency=low - use the patchfile modification time instead of the one from the "old" file - thanks to Philipp Weis for noticing! (Closes: #571541) * debian/rules: - - remove targets refering to CVS or arch as they are useless + - remove targets referring to CVS or arch as they are useless * apt-pkg/depcache.cc: - be doublesure that the killer query is empty before starting reinstall * methods/gpgv.cc: - remove the keyrings count limit by using vector magic + * contrib/mmap.cc: + - clarify "MMap reached size limit" error message, thanks Ivan Masár! [ Jari Aalto ] * debian/rules: - - spell out some less known options to reduce manpage consulation-rate + - spell out some less known options to reduce manpage consultation-rate - Use POSIX command substitution: $() - Remove EOL whitespace (Closes: #577804) -- cgit v1.2.3-70-g09d2 From 093e9f5d30f37164dd28d639fedfb059e105e43e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 31 May 2010 17:22:04 +0200 Subject: * apt-pkg/contrib/cmdline.cc: - fix segfault in SaveInConfig caused by writing over char[] sizes --- apt-pkg/contrib/cmndline.cc | 4 ++-- debian/changelog | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc index 0b16bf51a..5a9944096 100644 --- a/apt-pkg/contrib/cmndline.cc +++ b/apt-pkg/contrib/cmndline.cc @@ -360,11 +360,11 @@ bool CommandLine::DispatchArg(Dispatch *Map,bool NoMatch) than nothing after all. */ void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * const argv) { - char cmdline[300]; + char cmdline[100 + argc * 50]; unsigned int length = 0; bool lastWasOption = false; bool closeQuote = false; - for (unsigned int i = 0; i < argc; ++i, ++length) + for (unsigned int i = 0; i < argc && length < sizeof(cmdline); ++i, ++length) { for (unsigned int j = 0; argv[i][j] != '\0' && length < sizeof(cmdline)-1; ++j, ++length) { diff --git a/debian/changelog b/debian/changelog index 79768a779..6341484f2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -26,8 +26,10 @@ apt (0.7.26~exp6) UNRELEASED; urgency=low - add a simple wrapper around std::set for packages with it - move regex magic from apt-get to new FromRegEx method - move cmdline parsing from apt-cache to new FromCommandLine method + * apt-pkg/contrib/cmdline.cc: + - fix segfault in SaveInConfig caused by writing over char[] sizes - -- David Kalnischkies Sat, 29 May 2010 19:09:05 +0200 + -- David Kalnischkies Mon, 31 May 2010 17:21:00 +0200 apt (0.7.26~exp5) experimental; urgency=low -- cgit v1.2.3-70-g09d2 From cd8cf88f0e64e222e9fdcbf86e6cbbe09306040e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 8 Jun 2010 22:46:42 +0200 Subject: * apt-pkg/contrib/strutl.cc: - split StrToTime() into HTTP1.1 and FTP date parser methods and use strptime() instead of some selfmade scanf mangling --- apt-pkg/contrib/strutl.cc | 36 ++++++++++++++++++++++++++++++++++++ apt-pkg/contrib/strutl.h | 4 +++- debian/changelog | 3 +++ 3 files changed, 42 insertions(+), 1 deletion(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index c7d63ce8a..96e8143ec 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -855,6 +855,42 @@ static time_t timegm(struct tm *t) } #endif /*}}}*/ +// FullDateToTime - Converts a HTTP1.1 full date strings into a time_t /*{{{*/ +// --------------------------------------------------------------------- +/* tries to parses a full date as specified in RFC2616 Section 3.3.1 + with one exception: All timezones (%Z) are accepted but the protocol + says that it MUST be GMT, but this one is equal to UTC which we will + encounter from time to time (e.g. in Release files) so we accept all + here and just assume it is GMT (or UTC) later on */ +bool RFC1123StrToTime(const char* const str,time_t &time) +{ + struct tm Tm; + // Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 + if (strptime(str, "%a, %d %b %Y %H:%M:%S %Z", &Tm) == NULL && + // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 + strptime(str, "%A, %d-%b-%y %H:%M:%S %Z", &Tm) == NULL && + // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format + strptime(str, "%a %b %d %H:%M:%S %Y", &Tm) == NULL) + return false; + + time = timegm(&Tm); + return true; +} + /*}}}*/ +// FTPMDTMStrToTime - Converts a ftp modification date into a time_t /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool FTPMDTMStrToTime(const char* const str,time_t &time) +{ + struct tm Tm; + // MDTM includes no whitespaces but recommend and ignored by strptime + if (strptime(str, "%Y %m %d %H %M %S", &Tm) == NULL) + return false; + + time = timegm(&Tm); + return true; +} + /*}}}*/ // StrToTime - Converts a string into a time_t /*{{{*/ // --------------------------------------------------------------------- /* This handles all 3 populare time formats including RFC 1123, RFC 1036 diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index e509145f9..b5de0802e 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -45,7 +45,9 @@ string Base64Encode(const string &Str); string OutputInDepth(const unsigned long Depth, const char* Separator=" "); string URItoFileName(const string &URI); string TimeRFC1123(time_t Date); -bool StrToTime(const string &Val,time_t &Result); +bool RFC1123StrToTime(const char* const str,time_t &time) __attrib_const; +bool FTPMDTMStrToTime(const char* const str,time_t &time) __attrib_const; +__deprecated bool StrToTime(const string &Val,time_t &Result); string LookupTag(const string &Message,const char *Tag,const char *Default = 0); int StringToBool(const string &Text,int Default = -1); bool ReadMessages(int Fd, vector &List); diff --git a/debian/changelog b/debian/changelog index d8fb57757..2a40d084e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -44,6 +44,9 @@ apt (0.7.26~exp5) experimental; urgency=low - add 'disappear' to the known processing states, thanks Jonathan Nieder * apt-pkg/packagemanager.h: - export info about disappeared packages with GetDisappearedPackages() + * apt-pkg/contrib/strutl.cc: + - split StrToTime() into HTTP1.1 and FTP date parser methods and + use strptime() instead of some selfmade scanf mangling [ Michael Vogt ] * methods/http.{cc,h}: -- cgit v1.2.3-70-g09d2 From 550891457ff63db01b57d9057a5fe447a165e10c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 9 Jun 2010 00:27:22 +0200 Subject: use the portable timegm shown in his manpage instead of a strange looking code copycat from wget --- apt-pkg/contrib/strutl.cc | 36 ++++++++++++++++-------------------- debian/changelog | 2 ++ 2 files changed, 18 insertions(+), 20 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 96e8143ec..160450366 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -827,31 +827,27 @@ static int MonthConv(char *Month) } } /*}}}*/ -// timegm - Internal timegm function if gnu is not available /*{{{*/ +// timegm - Internal timegm if the gnu version is not available /*{{{*/ // --------------------------------------------------------------------- -/* Ripped this evil little function from wget - I prefer the use of - GNU timegm if possible as this technique will have interesting problems - with leap seconds, timezones and other. - - Converts struct tm to time_t, assuming the data in tm is UTC rather +/* Converts struct tm to time_t, assuming the data in tm is UTC rather than local timezone (mktime assumes the latter). - - Contributed by Roger Beeman , with the help of - Mark Baushke and the rest of the Gurus at CISCO. */ - -/* Turned it into an autoconf check, because GNU is not the only thing which - can provide timegm. -- 2002-09-22, Joel Baker */ -#ifndef HAVE_TIMEGM // Now with autoconf! + This function is a nonstandard GNU extension that is also present on + the BSDs and maybe other systems. For others we follow the advice of + the manpage of timegm and use his portable replacement. */ +#ifndef HAVE_TIMEGM static time_t timegm(struct tm *t) { - time_t tl, tb; - - tl = mktime (t); - if (tl == -1) - return -1; - tb = mktime (gmtime (&tl)); - return (tl <= tb ? (tl + (tl - tb)) : (tl - (tb - tl))); + char *tz = getenv("TZ"); + setenv("TZ", "", 1); + tzset(); + time_t ret = mktime(t); + if (tz) + setenv("TZ", tz, 1); + else + unsetenv("TZ"); + tzset(); + return ret; } #endif /*}}}*/ diff --git a/debian/changelog b/debian/changelog index fa0e667e7..049999230 100644 --- a/debian/changelog +++ b/debian/changelog @@ -47,6 +47,8 @@ apt (0.7.26~exp5) experimental; urgency=low * apt-pkg/contrib/strutl.cc: - split StrToTime() into HTTP1.1 and FTP date parser methods and use strptime() instead of some selfmade scanf mangling + - use the portable timegm shown in his manpage instead of a strange + looking code copycat from wget * ftparchive/writer.cc: - add ValidTime option to generate a Valid-Until header in Release file -- cgit v1.2.3-70-g09d2 From 96cc64a521957d63704de72ed95f1c839698c53c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 9 Jun 2010 00:53:44 +0200 Subject: move the users away from the deprecated StrToTime() method --- apt-pkg/acquire-method.cc | 2 +- apt-pkg/contrib/strutl.h | 4 ++-- methods/ftp.cc | 3 +-- methods/http.cc | 2 +- methods/rsh.cc | 3 +-- 5 files changed, 6 insertions(+), 8 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index fe066741c..b82dceecb 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -373,7 +373,7 @@ int pkgAcqMethod::Run(bool Single) Tmp->Uri = LookupTag(Message,"URI"); Tmp->DestFile = LookupTag(Message,"FileName"); - if (StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified) == false) + if (RFC1123StrToTime(LookupTag(Message,"Last-Modified").c_str(),Tmp->LastModified) == false) Tmp->LastModified = 0; Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false); Tmp->Next = 0; diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index b5de0802e..a457ff047 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -45,8 +45,8 @@ string Base64Encode(const string &Str); string OutputInDepth(const unsigned long Depth, const char* Separator=" "); string URItoFileName(const string &URI); string TimeRFC1123(time_t Date); -bool RFC1123StrToTime(const char* const str,time_t &time) __attrib_const; -bool FTPMDTMStrToTime(const char* const str,time_t &time) __attrib_const; +bool RFC1123StrToTime(const char* const str,time_t &time) __must_check; +bool FTPMDTMStrToTime(const char* const str,time_t &time) __must_check; __deprecated bool StrToTime(const string &Val,time_t &Result); string LookupTag(const string &Message,const char *Tag,const char *Default = 0); int StringToBool(const string &Text,int Default = -1); diff --git a/methods/ftp.cc b/methods/ftp.cc index 3e1725823..97248f900 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -661,8 +661,7 @@ bool FTPConn::ModTime(const char *Path, time_t &Time) return true; // Parse it - StrToTime(Msg,Time); - return true; + return FTPMDTMStrToTime(Msg.c_str(), Time); } /*}}}*/ // FTPConn::CreateDataFd - Get a data connection /*{{{*/ diff --git a/methods/http.cc b/methods/http.cc index d43dd14c8..5fdc62696 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -631,7 +631,7 @@ bool ServerState::HeaderLine(string Line) if (stringcasecmp(Tag,"Last-Modified:") == 0) { - if (StrToTime(Val,Date) == false) + if (RFC1123StrToTime(Val.c_str(), Date) == false) return _error->Error(_("Unknown date format")); return true; } diff --git a/methods/rsh.cc b/methods/rsh.cc index f0ccfc42d..97b4ef151 100644 --- a/methods/rsh.cc +++ b/methods/rsh.cc @@ -278,8 +278,7 @@ bool RSHConn::ModTime(const char *Path, time_t &Time) return false; // Parse it - StrToTime(Msg,Time); - return true; + return FTPMDTMStrToTime(Msg.c_str(), Time); } /*}}}*/ // RSHConn::Get - Get a file /*{{{*/ -- cgit v1.2.3-70-g09d2 From a3a03f5d7436c870edac9c0eb92e85e1fcaf6bca Mon Sep 17 00:00:00 2001 From: "martin@piware.de" <> Date: Wed, 9 Jun 2010 14:08:20 +0200 Subject: * apt-pkg/contrib/fileutl.{h,cc}: - Add support for transparent reading of gzipped files. - Link against zlib (in apt-pkg/makefile) and add zlib build dependency. --- apt-pkg/contrib/fileutl.cc | 47 ++++++++++++++++++++++++++++++++++++++++------ apt-pkg/contrib/fileutl.h | 9 ++++++--- apt-pkg/makefile | 2 +- debian/changelog | 6 ++++++ debian/control | 2 +- 5 files changed, 55 insertions(+), 11 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index da32983f1..11a9e7f7b 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -11,6 +11,7 @@ Most of this source is placed in the Public Domain, do with it what you will It was originally written by Jason Gunthorpe . + FileFd gzip support added by Martin Pitt The exception is RunScripts() it is under the GPLv2 @@ -603,6 +604,13 @@ bool FileFd::Open(string FileName,OpenMode Mode, unsigned long Perms) { case ReadOnly: iFd = open(FileName.c_str(),O_RDONLY); + if (iFd > 0 && FileName.compare(FileName.size()-3, 3, ".gz") == 0) { + gz = gzdopen (iFd, "r"); + if (gz == NULL) { + close (iFd); + iFd = -1; + } + } break; case WriteEmpty: @@ -658,7 +666,10 @@ bool FileFd::Read(void *To,unsigned long Size,unsigned long *Actual) do { - Res = read(iFd,To,Size); + if (gz != NULL) + Res = gzread(gz,To,Size); + else + Res = read(iFd,To,Size); if (Res < 0 && errno == EINTR) continue; if (Res < 0) @@ -697,7 +708,10 @@ bool FileFd::Write(const void *From,unsigned long Size) errno = 0; do { - Res = write(iFd,From,Size); + if (gz != NULL) + Res = gzwrite(gz,From,Size); + else + Res = write(iFd,From,Size); if (Res < 0 && errno == EINTR) continue; if (Res < 0) @@ -723,7 +737,12 @@ bool FileFd::Write(const void *From,unsigned long Size) /* */ bool FileFd::Seek(unsigned long To) { - if (lseek(iFd,To,SEEK_SET) != (signed)To) + int res; + if (gz) + res = gzseek(gz,To,SEEK_SET); + else + res = lseek(iFd,To,SEEK_SET); + if (res != (signed)To) { Flags |= Fail; return _error->Error("Unable to seek to %lu",To); @@ -737,7 +756,12 @@ bool FileFd::Seek(unsigned long To) /* */ bool FileFd::Skip(unsigned long Over) { - if (lseek(iFd,Over,SEEK_CUR) < 0) + int res; + if (gz) + res = gzseek(gz,Over,SEEK_CUR); + else + res = lseek(iFd,Over,SEEK_CUR); + if (res < 0) { Flags |= Fail; return _error->Error("Unable to seek ahead %lu",Over); @@ -751,6 +775,11 @@ bool FileFd::Skip(unsigned long Over) /* */ bool FileFd::Truncate(unsigned long To) { + if (gz) + { + Flags |= Fail; + return _error->Error("Truncating gzipped files is not implemented (%s)", FileName.c_str()); + } if (ftruncate(iFd,To) != 0) { Flags |= Fail; @@ -765,7 +794,11 @@ bool FileFd::Truncate(unsigned long To) /* */ unsigned long FileFd::Tell() { - off_t Res = lseek(iFd,0,SEEK_CUR); + off_t Res; + if (gz) + Res = gztell(gz); + else + Res = lseek(iFd,0,SEEK_CUR); if (Res == (off_t)-1) _error->Errno("lseek","Failed to determine the current file position"); return Res; @@ -776,6 +809,7 @@ unsigned long FileFd::Tell() /* */ unsigned long FileFd::Size() { + //TODO: For gz, do we need the actual file size here or the uncompressed length? struct stat Buf; if (fstat(iFd,&Buf) != 0) return _error->Errno("fstat","Unable to determine the file size"); @@ -789,9 +823,10 @@ bool FileFd::Close() { bool Res = true; if ((Flags & AutoClose) == AutoClose) - if (iFd >= 0 && close(iFd) != 0) + if ((gz != NULL && gzclose(gz) != 0) || (gz == NULL && iFd > 0 && close(iFd) != 0)) Res &= _error->Errno("close",_("Problem closing the file")); iFd = -1; + gz = NULL; if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail && FileName.empty() == false) diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 85a94898c..9925bbed4 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -25,6 +25,8 @@ #include #include +#include + using std::string; class FileFd @@ -36,6 +38,7 @@ class FileFd HitEof = (1<<3)}; unsigned long Flags; string FileName; + gzFile gz; public: enum OpenMode {ReadOnly,WriteEmpty,WriteExists,WriteAny,WriteTemp}; @@ -69,12 +72,12 @@ class FileFd inline string &Name() {return FileName;}; FileFd(string FileName,OpenMode Mode,unsigned long Perms = 0666) : iFd(-1), - Flags(0) + Flags(0), gz(NULL) { Open(FileName,Mode,Perms); }; - FileFd(int Fd = -1) : iFd(Fd), Flags(AutoClose) {}; - FileFd(int Fd,bool) : iFd(Fd), Flags(0) {}; + FileFd(int Fd = -1) : iFd(Fd), Flags(AutoClose), gz(NULL) {}; + FileFd(int Fd,bool) : iFd(Fd), Flags(0), gz(NULL) {}; virtual ~FileFd(); }; diff --git a/apt-pkg/makefile b/apt-pkg/makefile index bdd49c089..4cf07f3a8 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -14,7 +14,7 @@ include ../buildlib/libversion.mak LIBRARY=apt-pkg MAJOR=$(LIBAPTPKG_MAJOR) MINOR=$(LIBAPTPKG_RELEASE) -SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil -ldl +SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil -ldl -lz APT_DOMAIN:=libapt-pkg$(LIBAPTPKG_MAJOR) # Source code for the contributed non-core things diff --git a/debian/changelog b/debian/changelog index bc3da3679..2fba94d7c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,14 @@ apt (0.7.26~exp5) UNRELEASED; urgency=low + [ Christian Perrier ] * Slovak translation update. Closes: #581159 * Italian translation update. Closes: #581742 + [ Martin Pitt ] + * apt-pkg/contrib/fileutl.{h,cc}: + - Add support for transparent reading of gzipped files. + - Link against zlib (in apt-pkg/makefile) and add zlib build dependency. + -- Christian Perrier Tue, 11 May 2010 19:52:00 +0200 apt (0.7.26~exp4) unstable; urgency=low diff --git a/debian/control b/debian/control index 0c6f6b16d..58916a2b9 100644 --- a/debian/control +++ b/debian/control @@ -6,7 +6,7 @@ Uploaders: Michael Vogt , Otavio Salvador , Christian Perrier , Daniel Burrows , Luca Bruno , Julian Andres Klode Standards-Version: 3.8.4 -Build-Depends: debhelper (>= 5.0), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev | libcurl3-gnutls-dev (>= 7.15.5), debiandoc-sgml, xsltproc, docbook-xsl, po4a (>= 0.34-2), autotools-dev +Build-Depends: debhelper (>= 5.0), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev | libcurl3-gnutls-dev (>= 7.15.5), zlib1g-dev | libz-dev, debiandoc-sgml, xsltproc, docbook-xsl, po4a (>= 0.34-2), autotools-dev Vcs-Bzr: http://bzr.debian.org/apt/debian-sid/ Package: apt -- cgit v1.2.3-70-g09d2 From 24d7b6267ef3e475a153d4e2c4bcb30e1d14e671 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 9 Jun 2010 18:23:23 +0200 Subject: be sure that the RFC1123StrToTime method is run in a LANG=C environment --- apt-pkg/contrib/strutl.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 160450366..ace74cb37 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -861,12 +861,16 @@ static time_t timegm(struct tm *t) bool RFC1123StrToTime(const char* const str,time_t &time) { struct tm Tm; + setlocale (LC_ALL,"C"); + bool const invalid = // Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 - if (strptime(str, "%a, %d %b %Y %H:%M:%S %Z", &Tm) == NULL && + (strptime(str, "%a, %d %b %Y %H:%M:%S %Z", &Tm) == NULL && // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 strptime(str, "%A, %d-%b-%y %H:%M:%S %Z", &Tm) == NULL && // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format - strptime(str, "%a %b %d %H:%M:%S %Y", &Tm) == NULL) + strptime(str, "%a %b %d %H:%M:%S %Y", &Tm) == NULL); + setlocale (LC_ALL,""); + if (invalid == true) return false; time = timegm(&Tm); -- cgit v1.2.3-70-g09d2 From c4fc2fd7fa0fc63fd8cd6bc9b73492e6baf0222a Mon Sep 17 00:00:00 2001 From: "martin@piware.de" <> Date: Thu, 24 Jun 2010 21:27:27 +0200 Subject: Switch FileFd to not transparently gunzip, since that breaks code which expects the compressed contents to stay (such as the copy backend, or when using file:// repositories. Instead, introduce a new ReadOnlyGzip mode and use that where needed --- apt-pkg/acquire-item.cc | 4 ++-- apt-pkg/contrib/fileutl.cc | 14 +++++++++----- apt-pkg/contrib/fileutl.h | 2 +- apt-pkg/deb/debindexfile.cc | 6 +++--- apt-pkg/deb/debrecords.cc | 2 +- apt-pkg/deb/debsrcrecords.h | 2 +- cmdline/apt-cache.cc | 2 +- debian/changelog | 10 +++++++--- 8 files changed, 25 insertions(+), 17 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index fe81ee791..9abdb0ad0 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -228,7 +228,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ ss >> ServerSha1 >> size; unsigned long const ServerSize = atol(size.c_str()); - FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); + FileFd fd(CurrentPackagesFile, FileFd::ReadOnlyGzip); SHA1Summation SHA1; SHA1.AddFD(fd.Fd(), fd.Size()); string const local_sha1 = SHA1.Result(); @@ -459,7 +459,7 @@ bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ string FinalFile = _config->FindDir("Dir::State::lists"); FinalFile += URItoFileName(RealURI); - FileFd fd(FinalFile, FileFd::ReadOnly); + FileFd fd(FinalFile, FileFd::ReadOnlyGzip); SHA1Summation SHA1; SHA1.AddFD(fd.Fd(), fd.Size()); string local_sha1 = string(SHA1.Result()); diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 11a9e7f7b..2b91a46f7 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -604,12 +604,16 @@ bool FileFd::Open(string FileName,OpenMode Mode, unsigned long Perms) { case ReadOnly: iFd = open(FileName.c_str(),O_RDONLY); + break; + + case ReadOnlyGzip: + iFd = open(FileName.c_str(),O_RDONLY); if (iFd > 0 && FileName.compare(FileName.size()-3, 3, ".gz") == 0) { - gz = gzdopen (iFd, "r"); - if (gz == NULL) { - close (iFd); - iFd = -1; - } + gz = gzdopen (iFd, "r"); + if (gz == NULL) { + close (iFd); + iFd = -1; + } } break; diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 9925bbed4..c4b282126 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -41,7 +41,7 @@ class FileFd gzFile gz; public: - enum OpenMode {ReadOnly,WriteEmpty,WriteExists,WriteAny,WriteTemp}; + enum OpenMode {ReadOnly,WriteEmpty,WriteExists,WriteAny,WriteTemp,ReadOnlyGzip}; inline bool Read(void *To,unsigned long Size,bool AllowEof) { diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 9832329c0..7d7bd09fb 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -273,7 +273,7 @@ unsigned long debPackagesIndex::Size() const bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const { string PackageFile = IndexFile("Packages"); - FileFd Pkg(PackageFile,FileFd::ReadOnly); + FileFd Pkg(PackageFile,FileFd::ReadOnlyGzip); debListParser Parser(&Pkg); if (_error->PendingError() == true) return _error->Error("Problem opening %s",PackageFile.c_str()); @@ -464,7 +464,7 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const string TranslationFile = IndexFile(Language); if (TranslationsAvailable() && FileExists(TranslationFile)) { - FileFd Trans(TranslationFile,FileFd::ReadOnly); + FileFd Trans(TranslationFile,FileFd::ReadOnlyGzip); debListParser TransParser(&Trans); if (_error->PendingError() == true) return false; @@ -544,7 +544,7 @@ unsigned long debStatusIndex::Size() const /* */ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const { - FileFd Pkg(File,FileFd::ReadOnly); + FileFd Pkg(File,FileFd::ReadOnlyGzip); if (_error->PendingError() == true) return false; debListParser Parser(&Pkg); diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index 34ef0d8f2..ec9e395ef 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/apt-pkg/deb/debrecords.cc @@ -19,7 +19,7 @@ // --------------------------------------------------------------------- /* */ debRecordParser::debRecordParser(string FileName,pkgCache &Cache) : - File(FileName,FileFd::ReadOnly), + File(FileName,FileFd::ReadOnlyGzip), Tags(&File, std::max(Cache.Head().MaxVerFileSize, Cache.Head().MaxDescFileSize) + 200) { diff --git a/apt-pkg/deb/debsrcrecords.h b/apt-pkg/deb/debsrcrecords.h index c39d78bae..905264daa 100644 --- a/apt-pkg/deb/debsrcrecords.h +++ b/apt-pkg/deb/debsrcrecords.h @@ -48,7 +48,7 @@ class debSrcRecordParser : public pkgSrcRecords::Parser virtual bool Files(vector &F); debSrcRecordParser(string const &File,pkgIndexFile const *Index) - : Parser(Index), Fd(File,FileFd::ReadOnly), Tags(&Fd,102400), + : Parser(Index), Fd(File,FileFd::ReadOnlyGzip), Tags(&Fd,102400), Buffer(0), BufSize(0) {} ~debSrcRecordParser(); }; diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index 3f68579cc..2b47184f9 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -1220,7 +1220,7 @@ bool DisplayRecord(pkgCache::VerIterator V) if (I.IsOk() == false) return _error->Error(_("Package file %s is out of sync."),I.FileName()); - FileFd PkgF(I.FileName(),FileFd::ReadOnly); + FileFd PkgF(I.FileName(),FileFd::ReadOnlyGzip); if (_error->PendingError() == true) return false; diff --git a/debian/changelog b/debian/changelog index e44d7986d..f3f2d3df4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -9,13 +9,17 @@ apt (0.7.26~exp5) UNRELEASED; urgency=low - Make DEB_BUILD_OPTIONS=noopt actually work by passing the right CXXFLAGS. * apt-pkg/contrib/fileutl.{h,cc}: - - Add support for transparent reading of gzipped files. + - Add support for reading of gzipped files with the new "ReadOnlyGzip" + OpenMode. - Link against zlib (in apt-pkg/makefile) and add zlib build dependency. - [ABI BREAK] This adds a new private member to FileFd, but its - initialization is in the public header file. This also changes the - behaviour of FileFd for reading gzipped files. + initialization is in the public header file. * configure.in: - Check for zlib library and headers. + * apt-pkg/acquire-item.cc, apt-pkg/deb/debindexfile.cc, + apt-pkg/deb/debrecords.cc, apt-pkg/deb/debsrcrecords.h, + cmdline/apt-cache.cc: + - Open Packages, Sources, and Translations indexes in "ReadOnlyGzip" mode. * apt-pkg/deb/debindexfile.cc: - If we do not find uncompressed package/source/translation indexes, look for gzip compressed ones. -- cgit v1.2.3-70-g09d2 From 98ee7cd35cf205c52b3698ee91cec76d704a3937 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 25 Jun 2010 08:01:48 +0200 Subject: * apt-pkg/contrib/error.{cc,h}: - complete rewrite but use the same API - add NOTICE and DEBUG as new types of a message --- apt-pkg/contrib/error.cc | 333 ++++++++++++++++++++++------------------------- apt-pkg/contrib/error.h | 230 +++++++++++++++++++++++++++----- debian/changelog | 5 +- 3 files changed, 360 insertions(+), 208 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc index 927b7e05c..837d9e615 100644 --- a/apt-pkg/contrib/error.cc +++ b/apt-pkg/contrib/error.cc @@ -1,16 +1,15 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: error.cc,v 1.11 2002/03/26 07:38:58 jgg Exp $ /* ###################################################################### - - Global Erorr Class - Global error mechanism + + Global Error Class - Global error mechanism We use a simple STL vector to store each error record. A PendingFlag is kept which indicates when the vector contains a Sever error. - + This source is placed in the Public Domain, do with it what you will It was originally written by Jason Gunthorpe. - + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -19,7 +18,6 @@ #include #include #include -#include #include #include @@ -28,209 +26,188 @@ #include "config.h" /*}}}*/ -using namespace std; - // Global Error Object /*{{{*/ /* If the implementation supports posix threads then the accessor function is compiled to be thread safe otherwise a non-safe version is used. A Per-Thread error object is maintained in much the same manner as libc manages errno */ #if defined(_POSIX_THREADS) && defined(HAVE_PTHREAD) - #include - - static pthread_key_t ErrorKey; - static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;}; - static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);}; - - GlobalError *_GetErrorObj() - { - static pthread_once_t Once = PTHREAD_ONCE_INIT; - pthread_once(&Once,KeyAlloc); - - void *Res = pthread_getspecific(ErrorKey); - if (Res == 0) - pthread_setspecific(ErrorKey,Res = new GlobalError); - return (GlobalError *)Res; - } + #include + + static pthread_key_t ErrorKey; + static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;}; + static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);}; + + GlobalError *_GetErrorObj() { + static pthread_once_t Once = PTHREAD_ONCE_INIT; + pthread_once(&Once,KeyAlloc); + + void *Res = pthread_getspecific(ErrorKey); + if (Res == 0) + pthread_setspecific(ErrorKey,Res = new GlobalError); + return (GlobalError *)Res; + } #else - GlobalError *_GetErrorObj() - { - static GlobalError *Obj = new GlobalError; - return Obj; - } + GlobalError *_GetErrorObj() { + static GlobalError *Obj = new GlobalError; + return Obj; + } #endif /*}}}*/ - // GlobalError::GlobalError - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -GlobalError::GlobalError() : List(0), PendingFlag(false) -{ +GlobalError::GlobalError() : PendingFlag(false) {} + /*}}}*/ +// GlobalError::FatalE - Get part of the error string from errno /*{{{*/ +bool GlobalError::FatalE(const char *Function,const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(FATAL, Function, Description, args); } /*}}}*/ // GlobalError::Errno - Get part of the error string from errno /*{{{*/ -// --------------------------------------------------------------------- -/* Function indicates the stdlib function that failed and Description is - a user string that leads the text. Form is: - Description - Function (errno: strerror) - Carefull of the buffer overrun, sprintf. - */ -bool GlobalError::Errno(const char *Function,const char *Description,...) -{ - va_list args; - va_start(args,Description); - - // sprintf the description - char S[400]; - vsnprintf(S,sizeof(S),Description,args); - snprintf(S + strlen(S),sizeof(S) - strlen(S), - " - %s (%i: %s)",Function,errno,strerror(errno)); - - // Put it on the list - Item *Itm = new Item; - Itm->Text = S; - Itm->Error = true; - Insert(Itm); - - PendingFlag = true; - - return false; +bool GlobalError::Errno(const char *Function,const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(ERROR, Function, Description, args); } /*}}}*/ -// GlobalError::WarningE - Get part of the warn string from errno /*{{{*/ -// --------------------------------------------------------------------- -/* Function indicates the stdlib function that failed and Description is - a user string that leads the text. Form is: - Description - Function (errno: strerror) - Carefull of the buffer overrun, sprintf. - */ -bool GlobalError::WarningE(const char *Function,const char *Description,...) -{ - va_list args; - va_start(args,Description); - - // sprintf the description - char S[400]; - vsnprintf(S,sizeof(S),Description,args); - snprintf(S + strlen(S),sizeof(S) - strlen(S), - " - %s (%i: %s)",Function,errno,strerror(errno)); - - // Put it on the list - Item *Itm = new Item; - Itm->Text = S; - Itm->Error = false; - Insert(Itm); - - return false; +// GlobalError::WarningE - Get part of the warning string from errno /*{{{*/ +bool GlobalError::WarningE(const char *Function,const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(WARNING, Function, Description, args); +} + /*}}}*/ +// GlobalError::NoticeE - Get part of the notice string from errno /*{{{*/ +bool GlobalError::NoticeE(const char *Function,const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(NOTICE, Function, Description, args); +} + /*}}}*/ +// GlobalError::DebugE - Get part of the debug string from errno /*{{{*/ +bool GlobalError::DebugE(const char *Function,const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(DEBUG, Function, Description, args); +} + /*}}}*/ +// GlobalError::InsertErrno - formats an error message with the errno /*{{{*/ +bool GlobalError::InsertErrno(MsgType type, const char* Function, + const char* Description, va_list const &args) { + char S[400]; + vsnprintf(S,sizeof(S),Description,args); + snprintf(S + strlen(S),sizeof(S) - strlen(S), + " - %s (%i: %s)", Function, errno, strerror(errno)); + return Insert(type, S, args); +} + /*}}}*/ +// GlobalError::Fatal - Add a fatal error to the list /*{{{*/ +bool GlobalError::Fatal(const char *Description,...) { + va_list args; + va_start(args,Description); + return Insert(FATAL, Description, args); } /*}}}*/ // GlobalError::Error - Add an error to the list /*{{{*/ -// --------------------------------------------------------------------- -/* Just vsprintfs and pushes */ -bool GlobalError::Error(const char *Description,...) -{ - va_list args; - va_start(args,Description); - - // sprintf the description - char S[400]; - vsnprintf(S,sizeof(S),Description,args); - - // Put it on the list - Item *Itm = new Item; - Itm->Text = S; - Itm->Error = true; - Insert(Itm); - - PendingFlag = true; - - return false; +bool GlobalError::Error(const char *Description,...) { + va_list args; + va_start(args,Description); + return Insert(ERROR, Description, args); } /*}}}*/ // GlobalError::Warning - Add a warning to the list /*{{{*/ -// --------------------------------------------------------------------- -/* This doesn't set the pending error flag */ -bool GlobalError::Warning(const char *Description,...) +bool GlobalError::Warning(const char *Description,...) { + va_list args; + va_start(args,Description); + return Insert(WARNING, Description, args); +} + /*}}}*/ +// GlobalError::Notice - Add a notice to the list /*{{{*/ +bool GlobalError::Notice(const char *Description,...) { - va_list args; - va_start(args,Description); - - // sprintf the description - char S[400]; - vsnprintf(S,sizeof(S),Description,args); - - // Put it on the list - Item *Itm = new Item; - Itm->Text = S; - Itm->Error = false; - Insert(Itm); - - return false; + va_list args; + va_start(args,Description); + return Insert(NOTICE, Description, args); } /*}}}*/ -// GlobalError::PopMessage - Pulls a single message out /*{{{*/ -// --------------------------------------------------------------------- -/* This should be used in a loop checking empty() each cycle. It returns - true if the message is an error. */ -bool GlobalError::PopMessage(string &Text) +// GlobalError::Debug - Add a debug to the list /*{{{*/ +bool GlobalError::Debug(const char *Description,...) { - if (List == 0) - return false; - - bool Ret = List->Error; - Text = List->Text; - Item *Old = List; - List = List->Next; - delete Old; - - // This really should check the list to see if only warnings are left.. - if (List == 0) - PendingFlag = false; - - return Ret; + va_list args; + va_start(args,Description); + return Insert(DEBUG, Description, args); +} + /*}}}*/ +// GlobalError::Insert - Insert a new item at the end /*{{{*/ +bool GlobalError::Insert(MsgType type, const char* Description, + va_list const &args) { + char S[400]; + vsnprintf(S,sizeof(S),Description,args); + + Item const m(S, type); + Messages.push_back(m); + + if (type == ERROR || type == FATAL) + PendingFlag = true; + + if (type == FATAL || type == DEBUG) + std::clog << m << std::endl; + + return false; +} + /*}}}*/ +// GlobalError::PopMessage - Pulls a single message out /*{{{*/ +bool GlobalError::PopMessage(std::string &Text) { + if (Messages.empty() == true) + return false; + + Item const msg = Messages.front(); + Messages.pop_front(); + + bool const Ret = (msg.Type == ERROR || msg.Type == FATAL); + Text = msg.Text; + if (PendingFlag == false || Ret == false) + return Ret; + + // check if another error message is pending + for (std::list::const_iterator m = Messages.begin(); + m != Messages.end(); m++) + if (m->Type == ERROR || m->Type == FATAL) + return Ret; + + PendingFlag = false; + return Ret; } /*}}}*/ // GlobalError::DumpErrors - Dump all of the errors/warns to cerr /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void GlobalError::DumpErrors() -{ - // Print any errors or warnings found - string Err; - while (empty() == false) - { - bool Type = PopMessage(Err); - if (Type == true) - cerr << "E: " << Err << endl; - else - cerr << "W: " << Err << endl; - } +void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold) { + for (std::list::const_iterator m = Messages.begin(); + m != Messages.end(); m++) + if (m->Type >= trashhold) + out << (*m) << std::endl; + Discard(); } /*}}}*/ -// GlobalError::Discard - Discard /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void GlobalError::Discard() -{ - while (List != 0) - { - Item *Old = List; - List = List->Next; - delete Old; - } - - PendingFlag = false; +// GlobalError::Discard - Discard /*{{{*/ +void GlobalError::Discard() { + Messages.clear(); + PendingFlag = false; }; /*}}}*/ -// GlobalError::Insert - Insert a new item at the end /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void GlobalError::Insert(Item *Itm) -{ - Item **End = &List; - for (Item *I = List; I != 0; I = I->Next) - End = &I->Next; - Itm->Next = *End; - *End = Itm; +// GlobalError::empty - does our error list include anything? /*{{{*/ +bool GlobalError::empty(MsgType const &trashhold) const { + if (PendingFlag == true) + return false; + + if (Messages.empty() == true) + return true; + + for (std::list::const_iterator m = Messages.begin(); + m != Messages.end(); m++) + if (m->Type >= trashhold) + return false; + + return true; } /*}}}*/ diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index 8d5ec05ea..fc7b38f1b 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -42,43 +42,215 @@ #include +#include +#include #include -class GlobalError +#include + +class GlobalError /*{{{*/ { - struct Item - { - std::string Text; - bool Error; - Item *Next; - }; - - Item *List; - bool PendingFlag; - void Insert(Item *I); - - public: +public: /*{{{*/ + /** \brief a message can have one of following severity */ + enum MsgType { + /** \brief Message will be printed instantly as it is likely that + this error will lead to a complete crash */ + FATAL = 40, + /** \brief An error does hinder the correct execution and should be corrected */ + ERROR = 30, + /** \brief indicates problem that can lead to errors later on */ + WARNING = 20, + /** \brief deprecation warnings, old fallback behavior, … */ + NOTICE = 10, + /** \brief for developers only in areas it is hard to print something directly */ + DEBUG = 0 + }; - // Call to generate an error from a library call. - bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold; - bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold; + /** \brief add a fatal error message with errno to the list + * + * \param Function name of the function generating the error + * \param Description format string for the error message + * + * \return \b false + */ + bool FatalE(const char *Function,const char *Description,...) __like_printf(3) __cold; - /* A warning should be considered less severe than an error, and may be - ignored by the client. */ - bool Error(const char *Description,...) __like_printf(2) __cold; - bool Warning(const char *Description,...) __like_printf(2) __cold; + /** \brief add an Error message with errno to the list + * + * \param Function name of the function generating the error + * \param Description format string for the error message + * + * \return \b false + */ + bool Errno(const char *Function,const char *Description,...) __like_printf(3) __cold; - // Simple accessors - inline bool PendingError() {return PendingFlag;}; - inline bool empty() {return List == 0;}; - bool PopMessage(std::string &Text); - void Discard(); + /** \brief add a warning message with errno to the list + * + * A warning should be considered less severe than an error and + * may be ignored by the client. + * + * \param Function Name of the function generates the warning. + * \param Description Format string for the warning message. + * + * \return \b false + */ + bool WarningE(const char *Function,const char *Description,...) __like_printf(3) __cold; - // Usefull routine to dump to cerr - void DumpErrors(); - - GlobalError(); + /** \brief add a notice message with errno to the list + * + * \param Function name of the function generating the error + * \param Description format string for the error message + * + * \return \b false + */ + bool NoticeE(const char *Function,const char *Description,...) __like_printf(3) __cold; + + /** \brief add a debug message with errno to the list + * + * \param Function name of the function generating the error + * \param Description format string for the error message + * + * \return \b false + */ + bool DebugE(const char *Function,const char *Description,...) __like_printf(3) __cold; + + /** \brief add an fatal error message to the list + * + * Most of the stuff we consider as "error" is also "fatal" for + * the user as the application will not have the expected result, + * but a fatal message here means that it gets printed directly + * to stderr in addiction to adding it to the list as the error + * leads sometimes to crashes and a maybe duplicated message + * is better than "Segfault" as the only displayed text + * + * \param Description Format string for the fatal error message. + * + * \return \b false + */ + bool Fatal(const char *Description,...) __like_printf(2) __cold; + + /** \brief add an Error message to the list + * + * \param Description Format string for the error message. + * + * \return \b false + */ + bool Error(const char *Description,...) __like_printf(2) __cold; + + /** \brief add a warning message to the list + * + * A warning should be considered less severe than an error and + * may be ignored by the client. + * + * \param Description Format string for the message + * + * \return \b false + */ + bool Warning(const char *Description,...) __like_printf(2) __cold; + + /** \brief add a notice message to the list + * + * A notice should be considered less severe than an error or a + * warning and can be ignored by the client without further problems + * for some times, but he should consider fixing the problem. + * This error type can be used for e.g. deprecation warnings of options. + * + * \param Description Format string for the message + * + * \return \b false + */ + bool Notice(const char *Description,...) __like_printf(2) __cold; + + /** \brief add a debug message to the list + * + * \param Description Format string for the message + * + * \return \b false + */ + bool Debug(const char *Description,...) __like_printf(2) __cold; + + /** \brief is an error in the list? + * + * \return \b true if an error is included in the list, \b false otherwise + */ + inline bool PendingError() const {return PendingFlag;}; + + /** \brief is the list empty? + * + * The default checks if the list is empty or contains only notices, + * if you want to check if also no notices happend set the parameter + * flag to \b false. + * + * \param WithoutNotice does notices count, default is \b true, so no + * + * \return \b true if an the list is empty, \b false otherwise + */ + bool empty(MsgType const &trashhold = WARNING) const; + + /** \brief returns and removes the first (or last) message in the list + * + * \param[out] Text message of the first/last item + * + * \return \b true if the message was an error, \b false otherwise + */ + bool PopMessage(std::string &Text); + + /** \brief clears the list of messages */ + void Discard(); + + /** \brief outputs the list of messages to the given stream + * + * Note that all messages are discarded, also the notices + * displayed or not. + * + * \param[out] out output stream to write the messages in + * \param WithoutNotice output notices or not + */ + void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING); + + /** \brief dumps the list of messages to std::cerr + * + * Note that all messages are discarded, also the notices + * displayed or not. + * + * \param WithoutNotice print notices or not + */ + void inline DumpErrors(MsgType const &trashhold = WARNING) { + DumpErrors(std::cerr, trashhold); + } + + GlobalError(); + /*}}}*/ +private: /*{{{*/ + struct Item { + std::string Text; + MsgType Type; + + Item(char const *Text, MsgType const &Type) : + Text(Text), Type(Type) {}; + + friend std::ostream& operator<< (std::ostream &out, Item i) { + switch(i.Type) { + case FATAL: + case ERROR: out << "E"; break; + case WARNING: out << "W"; break; + case NOTICE: out << "N"; break; + case DEBUG: out << "D"; break; + } + return out << ": " << i.Text; + } + }; + + std::list Messages; + bool PendingFlag; + + bool InsertErrno(MsgType type, const char* Function, + const char* Description, va_list const &args); + bool Insert(MsgType type, const char* Description, + va_list const &args); + /*}}}*/ }; + /*}}}*/ // The 'extra-ansi' syntax is used to help with collisions. GlobalError *_GetErrorObj(); diff --git a/debian/changelog b/debian/changelog index 00877eefb..3e7b16d62 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,8 +16,11 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/depcache.cc: - SetCandidateVer for all pseudo packages - SetReInstall for the "all" package of a pseudo package + * apt-pkg/contrib/error.{cc,h}: + - complete rewrite but use the same API + - add NOTICE and DEBUG as new types of a message - -- David Kalnischkies Thu, 10 Jun 2010 16:36:58 +0200 + -- David Kalnischkies Fri, 25 Jun 2010 08:01:14 +0200 apt (0.7.26~exp7) experimental; urgency=low -- cgit v1.2.3-70-g09d2 From c4ba7c44ff03d67ff982bbab26dc48d796041e02 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 25 Jun 2010 19:16:12 +0200 Subject: add a simple stack handling to be able to delay error handling --- apt-pkg/contrib/error.cc | 32 ++++++++++++++++- apt-pkg/contrib/error.h | 35 ++++++++++++++++++- debian/changelog | 3 +- test/libapt/globalerror_test.cc | 77 +++++++++++++++++++++++++++++++++++++++++ test/libapt/makefile | 10 ++++-- 5 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 test/libapt/globalerror_test.cc (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc index 837d9e615..8cee21c9c 100644 --- a/apt-pkg/contrib/error.cc +++ b/apt-pkg/contrib/error.cc @@ -181,7 +181,13 @@ bool GlobalError::PopMessage(std::string &Text) { } /*}}}*/ // GlobalError::DumpErrors - Dump all of the errors/warns to cerr /*{{{*/ -void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold) { +void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold, + bool const &mergeStack) { + if (mergeStack == true) + for (std::list::const_reverse_iterator s = Stacks.rbegin(); + s != Stacks.rend(); ++s) + Messages.insert(Messages.begin(), s->Messages.begin(), s->Messages.end()); + for (std::list::const_iterator m = Messages.begin(); m != Messages.end(); m++) if (m->Type >= trashhold) @@ -211,3 +217,27 @@ bool GlobalError::empty(MsgType const &trashhold) const { return true; } /*}}}*/ +// GlobalError::PushToStack /*{{{*/ +void GlobalError::PushToStack() { + MsgStack pack(Messages, PendingFlag); + Stacks.push_back(pack); + Discard(); +} + /*}}}*/ +// GlobalError::RevertToStack /*{{{*/ +void GlobalError::RevertToStack() { + Discard(); + MsgStack pack = Stacks.back(); + Messages = pack.Messages; + PendingFlag = pack.PendingFlag; + Stacks.pop_back(); +} + /*}}}*/ +// GlobalError::MergeWithStack /*{{{*/ +void GlobalError::MergeWithStack() { + MsgStack pack = Stacks.back(); + Messages.insert(Messages.begin(), pack.Messages.begin(), pack.Messages.end()); + PendingFlag = PendingFlag || pack.PendingFlag; + Stacks.pop_back(); +} + /*}}}*/ diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index fc7b38f1b..73735162d 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -206,7 +206,8 @@ public: /*{{{*/ * \param[out] out output stream to write the messages in * \param WithoutNotice output notices or not */ - void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING); + void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING, + bool const &mergeStack = true); /** \brief dumps the list of messages to std::cerr * @@ -219,6 +220,28 @@ public: /*{{{*/ DumpErrors(std::cerr, trashhold); } + /** \brief put the current Messages into the stack + * + * All "old" messages will be pushed into a stack to + * them later back, but for now the Message query will be + * empty and performs as no messages were present before. + * + * The stack can be as deep as you want - all stack operations + * will only operate on the last element in the stack. + */ + void PushToStack(); + + /** \brief throw away all current messages */ + void RevertToStack(); + + /** \brief merge current and stack together */ + void MergeWithStack(); + + /** \brief return the deep of the stack */ + size_t StackCount() const { + return Stacks.size(); + } + GlobalError(); /*}}}*/ private: /*{{{*/ @@ -244,6 +267,16 @@ private: /*{{{*/ std::list Messages; bool PendingFlag; + struct MsgStack { + std::list const Messages; + bool const PendingFlag; + + MsgStack(std::list const &Messages, bool const &Pending) : + Messages(Messages), PendingFlag(Pending) {}; + }; + + std::list Stacks; + bool InsertErrno(MsgType type, const char* Function, const char* Description, va_list const &args); bool Insert(MsgType type, const char* Description, diff --git a/debian/changelog b/debian/changelog index 3e7b16d62..46e371165 100644 --- a/debian/changelog +++ b/debian/changelog @@ -19,8 +19,9 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/contrib/error.{cc,h}: - complete rewrite but use the same API - add NOTICE and DEBUG as new types of a message + - add a simple stack handling to be able to delay error handling - -- David Kalnischkies Fri, 25 Jun 2010 08:01:14 +0200 + -- David Kalnischkies Fri, 25 Jun 2010 19:15:21 +0200 apt (0.7.26~exp7) experimental; urgency=low diff --git a/test/libapt/globalerror_test.cc b/test/libapt/globalerror_test.cc new file mode 100644 index 000000000..b2752255f --- /dev/null +++ b/test/libapt/globalerror_test.cc @@ -0,0 +1,77 @@ +#include + +#include "assert.h" +#include + +int main(int argc,char *argv[]) +{ + equals(_error->empty(), true); + equals(_error->PendingError(), false); + equals(_error->Notice("%s Notice", "A"), false); + equals(_error->empty(), true); + equals(_error->empty(GlobalError::DEBUG), false); + equals(_error->PendingError(), false); + equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false); + equals(_error->PendingError(), true); + std::string text; + equals(_error->PopMessage(text), false); + equals(_error->PendingError(), true); + equals(text, "A Notice"); + equals(_error->PopMessage(text), true); + equals(text, "Something horrible happend 2 times"); + equals(_error->empty(GlobalError::DEBUG), true); + equals(_error->PendingError(), false); + equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false); + equals(_error->PendingError(), true); + equals(_error->empty(GlobalError::FATAL), false); + _error->Discard(); + + equals(_error->empty(), true); + equals(_error->PendingError(), false); + equals(_error->Notice("%s Notice", "A"), false); + equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false); + equals(_error->PendingError(), true); + equals(_error->empty(GlobalError::NOTICE), false); + _error->PushToStack(); + equals(_error->empty(GlobalError::NOTICE), true); + equals(_error->PendingError(), false); + equals(_error->Warning("%s Warning", "A"), false); + equals(_error->empty(GlobalError::ERROR), true); + equals(_error->PendingError(), false); + _error->RevertToStack(); + equals(_error->empty(GlobalError::ERROR), false); + equals(_error->PendingError(), true); + equals(_error->PopMessage(text), false); + equals(_error->PendingError(), true); + equals(text, "A Notice"); + equals(_error->PopMessage(text), true); + equals(text, "Something horrible happend 2 times"); + equals(_error->PendingError(), false); + equals(_error->empty(), true); + + equals(_error->Notice("%s Notice", "A"), false); + equals(_error->Error("%s horrible %s %d times", "Something", "happend", 2), false); + equals(_error->PendingError(), true); + equals(_error->empty(GlobalError::NOTICE), false); + _error->PushToStack(); + equals(_error->empty(GlobalError::NOTICE), true); + equals(_error->PendingError(), false); + equals(_error->Warning("%s Warning", "A"), false); + equals(_error->empty(GlobalError::ERROR), true); + equals(_error->PendingError(), false); + _error->MergeWithStack(); + equals(_error->empty(GlobalError::ERROR), false); + equals(_error->PendingError(), true); + equals(_error->PopMessage(text), false); + equals(_error->PendingError(), true); + equals(text, "A Notice"); + equals(_error->PopMessage(text), true); + equals(text, "Something horrible happend 2 times"); + equals(_error->PendingError(), false); + equals(_error->empty(), false); + equals(_error->PopMessage(text), false); + equals(text, "A Warning"); + equals(_error->empty(), true); + + return 0; +} diff --git a/test/libapt/makefile b/test/libapt/makefile index ee3401b35..50058262e 100644 --- a/test/libapt/makefile +++ b/test/libapt/makefile @@ -30,13 +30,19 @@ SOURCE = getlistoffilesindir_test.cc include $(PROGRAM_H) # Program for testing CommandLine reconstruction -PROGRAM = commandlineasstring${BASENAME} +PROGRAM = CommandlineAsString${BASENAME} SLIBS = -lapt-pkg SOURCE = commandlineasstring_test.cc include $(PROGRAM_H) # Program for testing debians version comparing -PROGRAM = compareversion${BASENAME} +PROGRAM = CompareVersion${BASENAME} SLIBS = -lapt-pkg SOURCE = compareversion_test.cc include $(PROGRAM_H) + +# test the GlobalError stack class +PROGRAM = GlobalError${BASENAME} +SLIBS = -lapt-pkg +SOURCE = globalerror_test.cc +include $(PROGRAM_H) -- cgit v1.2.3-70-g09d2 From 1f2933a8de0f3a26f51b4a0a2112cbdfd4461e9b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 Jun 2010 13:29:24 +0200 Subject: - use the new MatchAgainstConfig for the DefaultRootSetFunc * apt-pkg/contrib/configuration.{cc,h}: - add a wrapper to match strings against configurable regex patterns --- apt-pkg/contrib/configuration.cc | 43 +++++++++++++++++++++++++++++++++++ apt-pkg/contrib/configuration.h | 19 +++++++++++++++- apt-pkg/depcache.cc | 48 ---------------------------------------- apt-pkg/depcache.h | 22 +++++------------- debian/changelog | 5 ++++- 5 files changed, 71 insertions(+), 66 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 9129d92f0..81cc87d15 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -843,3 +843,46 @@ bool ReadConfigDir(Configuration &Conf,const string &Dir, return true; } /*}}}*/ +// MatchAgainstConfig Constructor /*{{{*/ +Configuration::MatchAgainstConfig::MatchAgainstConfig(char const * Config) +{ + std::vector const strings = _config->FindVector(Config); + for (std::vector::const_iterator s = strings.begin(); + s != strings.end(); ++s) + { + regex_t *p = new regex_t; + if (regcomp(p, s->c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB) == 0) + patterns.push_back(p); + else + { + regfree(p); + delete p; + _error->Warning("Regex compilation error for '%s' in configuration option '%s'", + s->c_str(), Config); + } + } + +} + /*}}}*/ +// MatchAgainstConfig Destructor /*{{{*/ +Configuration::MatchAgainstConfig::~MatchAgainstConfig() +{ + for(std::vector::const_iterator p = patterns.begin(); + p != patterns.end(); ++p) + { + regfree(*p); + delete *p; + } +} + /*}}}*/ +// MatchAgainstConfig::Match - returns true if a pattern matches /*{{{*/ +bool Configuration::MatchAgainstConfig::Match(char const * str) const +{ + for(std::vector::const_iterator p = patterns.begin(); + p != patterns.end(); ++p) + if (regexec(*p, str, 0, 0, 0) == 0) + return true; + + return false; +} + /*}}}*/ diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index 2494c1d7c..cbe18e4e5 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -28,7 +28,7 @@ #ifndef PKGLIB_CONFIGURATION_H #define PKGLIB_CONFIGURATION_H - +#include #include #include @@ -104,6 +104,23 @@ class Configuration Configuration(const Item *Root); Configuration(); ~Configuration(); + + /** \brief match a string against a configurable list of patterns */ + class MatchAgainstConfig + { + std::vector patterns; + + public: + MatchAgainstConfig(char const * Config); + virtual ~MatchAgainstConfig(); + + /** \brief Returns \b true for a string matching one of the patterns */ + bool Match(char const * str) const; + bool Match(std::string const &str) const { return Match(str.c_str()); }; + + /** \brief returns if the matcher setup was successful */ + bool wasConstructedSuccessfully() const { return patterns.empty() == false; } + }; }; extern Configuration *_config; diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index d082b8404..8bca3e36e 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1635,54 +1635,6 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep) else if(Dep->Type == pkgCache::Dep::Suggests) return _config->FindB("APT::Install-Suggests", false); - return false; -} - /*}}}*/ -pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc() /*{{{*/ - : constructedSuccessfully(false) -{ - Configuration::Item const *Opts; - Opts = _config->Tree("APT::NeverAutoRemove"); - if (Opts != 0 && Opts->Child != 0) - { - Opts = Opts->Child; - for (; Opts != 0; Opts = Opts->Next) - { - if (Opts->Value.empty() == true) - continue; - - regex_t *p = new regex_t; - if(regcomp(p,Opts->Value.c_str(), - REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0) - { - regfree(p); - delete p; - _error->Error("Regex compilation error for APT::NeverAutoRemove"); - return; - } - - rootSetRegexp.push_back(p); - } - } - - constructedSuccessfully = true; -} - /*}}}*/ -pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc() /*{{{*/ -{ - for(unsigned int i = 0; i < rootSetRegexp.size(); i++) - { - regfree(rootSetRegexp[i]); - delete rootSetRegexp[i]; - } -} - /*}}}*/ -bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg) /*{{{*/ -{ - for(unsigned int i = 0; i < rootSetRegexp.size(); i++) - if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0) - return true; - return false; } /*}}}*/ diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 72d7cce5d..66c099b80 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -38,11 +38,10 @@ #ifndef PKGLIB_DEPCACHE_H #define PKGLIB_DEPCACHE_H - +#include #include #include - -#include +#include #include #include @@ -184,22 +183,13 @@ class pkgDepCache : protected pkgCache::Namespace /** \brief Returns \b true for packages matching a regular * expression in APT::NeverAutoRemove. */ - class DefaultRootSetFunc : public InRootSetFunc + class DefaultRootSetFunc : public InRootSetFunc, public Configuration::MatchAgainstConfig { - std::vector rootSetRegexp; - bool constructedSuccessfully; - public: - DefaultRootSetFunc(); - ~DefaultRootSetFunc(); - - /** \return \b true if the class initialized successfully, \b - * false otherwise. Used to avoid throwing an exception, since - * APT classes generally don't. - */ - bool wasConstructedSuccessfully() const { return constructedSuccessfully; } + DefaultRootSetFunc() : Configuration::MatchAgainstConfig("APT::NeverRemove") {}; + virtual ~DefaultRootSetFunc() {}; - bool InRootSet(const pkgCache::PkgIterator &pkg); + bool InRootSet(const pkgCache::PkgIterator &pkg) { return pkg.end() == true && Match(pkg.Name()); }; }; struct StateCache diff --git a/debian/changelog b/debian/changelog index 06bde48fc..4500614a0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,14 +16,17 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/depcache.cc: - SetCandidateVer for all pseudo packages - SetReInstall for the "all" package of a pseudo package + - use the new MatchAgainstConfig for the DefaultRootSetFunc * apt-pkg/contrib/error.{cc,h}: - complete rewrite but use the same API - add NOTICE and DEBUG as new types of a message - add a simple stack handling to be able to delay error handling * apt-pkg/aptconfiguration.cc: - show a deprecation notice for APT::Acquire::Translation + * apt-pkg/contrib/configuration.{cc,h}: + - add a wrapper to match strings against configurable regex patterns - -- David Kalnischkies Sat, 26 Jun 2010 09:01:40 +0200 + -- David Kalnischkies Sat, 26 Jun 2010 13:28:48 +0200 apt (0.7.26~exp7) experimental; urgency=low -- cgit v1.2.3-70-g09d2 From 1408e219e76e577fb84ef1c48e58337b6569feec Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 Jun 2010 18:40:15 +0200 Subject: * apt-pkg/contrib/fileutl.cc: - show notice about ignored file instead of being always silent - add a Dir::Ignore-Files-Silently list option to control the notice * --- apt-pkg/contrib/fileutl.cc | 4 ++++ apt-pkg/init.cc | 5 +++++ debian/changelog | 6 +++++- doc/apt.conf.5.xml | 9 +++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 16f7ce929..e95ddf562 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -281,6 +281,7 @@ std::vector GetListOfFilesInDir(string const &Dir, std::vector c } std::vector List; + Configuration::MatchAgainstConfig SilentIgnore("Dir::Ignore-Files-Silently"); DIR *D = opendir(Dir.c_str()); if (D == 0) { @@ -306,6 +307,7 @@ std::vector GetListOfFilesInDir(string const &Dir, std::vector c { if (Debug == true) std::clog << "Bad file: " << Ent->d_name << " → no extension" << std::endl; + _error->Notice("Ignoring file '%s' in directory '%s' as it has no filename extension", Ent->d_name, Dir.c_str()); continue; } } @@ -313,6 +315,8 @@ std::vector GetListOfFilesInDir(string const &Dir, std::vector c { if (Debug == true) std::clog << "Bad file: " << Ent->d_name << " → bad extension »" << flExtension(Ent->d_name) << "«" << std::endl; + if (SilentIgnore.Match(Ent->d_name) == false) + _error->Notice("Ignoring file '%s' in directory '%s' as it has an invalid filename extension", Ent->d_name, Dir.c_str()); continue; } } diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index 21472eb3b..7a332c86e 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -78,6 +78,11 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.Set("Dir::Log::Terminal","term.log"); Cnf.Set("Dir::Log::History","history.log"); + Cnf.Set("Dir::Ignore-Files-Silently::", "~$"); + Cnf.Set("Dir::Ignore-Files-Silently::", "\\.disabled$"); + Cnf.Set("Dir::Ignore-Files-Silently::", "\\.bak$"); + Cnf.Set("Dir::Ignore-Files-Silently::", "\\.dpkg-[a-z]+$"); + // Translation Cnf.Set("APT::Acquire::Translation", "environment"); diff --git a/debian/changelog b/debian/changelog index 4500614a0..722e7ffc4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -25,8 +25,12 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low - show a deprecation notice for APT::Acquire::Translation * apt-pkg/contrib/configuration.{cc,h}: - add a wrapper to match strings against configurable regex patterns + * apt-pkg/contrib/fileutl.cc: + - show notice about ignored file instead of being always silent + - add a Dir::Ignore-Files-Silently list option to control the notice + * - -- David Kalnischkies Sat, 26 Jun 2010 13:28:48 +0200 + -- David Kalnischkies Sat, 26 Jun 2010 18:40:01 +0200 apt (0.7.26~exp7) experimental; urgency=low diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index 0cf4bb663..39e2c8e6b 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -507,6 +507,15 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; will be looked up in /tmp/staging/var/lib/dpkg/status. + + + The Ignore-Files-Silently list can be used to specify + which files APT should silently ignore while parsing the files in the + fragment directories. Per default a file which end with .disabled, + ~, .bak or .dpkg-[a-z]+ + is silently ignored. As seen in the last default value these patterns can use regular + expression syntax. + APT in DSelect -- cgit v1.2.3-70-g09d2 From 5afa55c6703a71a198aac950db30ffc6ca49f269 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 26 Jun 2010 18:42:42 +0200 Subject: make the MMap Grow Error a fatal one as while in theory the code should never segfault it still tend to do it so better show it directly --- apt-pkg/contrib/mmap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index d233e51bc..d71066243 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -297,7 +297,7 @@ unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln) { if(!Grow()) { - _error->Error(_("Dynamic MMap ran out of room. Please increase the size " + _error->Fatal(_("Dynamic MMap ran out of room. Please increase the size " "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace); return 0; } -- cgit v1.2.3-70-g09d2 From 3010fb0e069d2fd4c7a6ade4559bfb659bf8f2fb Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 29 Jun 2010 17:23:24 +0200 Subject: * apt-pkg/contrib/fileutl.cc: - Make FileFd replace files atomically in WriteTemp mode (for cache, etc). --- apt-pkg/contrib/fileutl.cc | 20 +++++++++++++++----- apt-pkg/contrib/fileutl.h | 3 ++- debian/changelog | 2 ++ 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 16f7ce929..0b0739cda 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -654,10 +655,11 @@ bool FileFd::Open(string FileName,OpenMode Mode, unsigned long Perms) case WriteEmpty: { - struct stat Buf; - if (lstat(FileName.c_str(),&Buf) == 0 && S_ISLNK(Buf.st_mode)) - unlink(FileName.c_str()); - iFd = open(FileName.c_str(),O_RDWR | O_CREAT | O_TRUNC,Perms); + Flags |= Replace; + char *name = strdup((FileName + ".XXXXXX").c_str()); + TemporaryFileName = string(mktemp(name)); + iFd = open(TemporaryFileName.c_str(),O_RDWR | O_CREAT | O_EXCL,Perms); + free(name); break; } @@ -839,11 +841,19 @@ bool FileFd::Close() if (iFd >= 0 && close(iFd) != 0) Res &= _error->Errno("close",_("Problem closing the file")); iFd = -1; - + + if ((Flags & Replace) == Replace) { + FileName = TemporaryFileName; // for the unlink() below. + if (rename(TemporaryFileName.c_str(), FileName.c_str()) != 0) + Res &= _error->Errno("rename",_("Problem renaming the file")); + } + if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail && FileName.empty() == false) if (unlink(FileName.c_str()) != 0) Res &= _error->WarningE("unlnk",_("Problem unlinking the file")); + + return Res; } /*}}}*/ diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 003bd9b83..528725f89 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -34,9 +34,10 @@ class FileFd int iFd; enum LocalFlags {AutoClose = (1<<0),Fail = (1<<1),DelOnFail = (1<<2), - HitEof = (1<<3)}; + HitEof = (1<<3), Replace = (1<<4) }; unsigned long Flags; string FileName; + string TemporaryFileName; public: enum OpenMode {ReadOnly,WriteEmpty,WriteExists,WriteAny,WriteTemp}; diff --git a/debian/changelog b/debian/changelog index 3a0fcd83d..1bf6815a5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,8 @@ apt (0.7.26~exp8) experimental; urgency=low - Support matching pins by regular expressions or glob() like patterns, regular expressions have to be put between to slashes; for example, /.*/. + * apt-pkg/contrib/fileutl.cc: + - Make FileFd replace files atomically in WriteTemp mode (for cache, etc). * debian/control: - Set Standards-Version to 3.9.0 -- cgit v1.2.3-70-g09d2 From fd3b761e8cba6ed626639b50b1221246098c7b3a Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Tue, 29 Jun 2010 17:28:33 +0200 Subject: Fix the atomic replace. --- apt-pkg/contrib/fileutl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 0b0739cda..0b62d1bd8 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -843,9 +843,9 @@ bool FileFd::Close() iFd = -1; if ((Flags & Replace) == Replace) { - FileName = TemporaryFileName; // for the unlink() below. if (rename(TemporaryFileName.c_str(), FileName.c_str()) != 0) Res &= _error->Errno("rename",_("Problem renaming the file")); + FileName = TemporaryFileName; // for the unlink() below. } if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail && -- cgit v1.2.3-70-g09d2 From d13c2d3f7b10e558301a05948e91ac4a60160793 Mon Sep 17 00:00:00 2001 From: "martin@piware.de" <> Date: Tue, 6 Jul 2010 12:48:06 +0200 Subject: FileFd(): Drop file name extension check in ReadOnlyGzip mode Drop the ".gz" extension check in FileFd::Open() in ReadOnlyGzip mode, to not depend on a particular file extension. This allows rewriting the gzip method using internal decompression (on ".decomp" files). This requires a zlib bug workaround in FileFd::Close(): When opening an empty file with gzdopen(), gzclose() fails with Z_BUF_ERROR. Do not count this as a failure. --- apt-pkg/contrib/fileutl.cc | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 2b91a46f7..0d2d3f356 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -608,7 +608,7 @@ bool FileFd::Open(string FileName,OpenMode Mode, unsigned long Perms) case ReadOnlyGzip: iFd = open(FileName.c_str(),O_RDONLY); - if (iFd > 0 && FileName.compare(FileName.size()-3, 3, ".gz") == 0) { + if (iFd > 0) { gz = gzdopen (iFd, "r"); if (gz == NULL) { close (iFd); @@ -827,8 +827,16 @@ bool FileFd::Close() { bool Res = true; if ((Flags & AutoClose) == AutoClose) - if ((gz != NULL && gzclose(gz) != 0) || (gz == NULL && iFd > 0 && close(iFd) != 0)) - Res &= _error->Errno("close",_("Problem closing the file")); + { + if (gz != NULL) { + int e = gzclose(gz); + // gzdopen() on empty files always fails with "buffer error" here, ignore that + if (e != 0 && e != Z_BUF_ERROR) + Res &= _error->Errno("close",_("Problem closing the gzip file")); + } else + if (iFd > 0 && close(iFd) != 0) + Res &= _error->Errno("close",_("Problem closing the file")); + } iFd = -1; gz = NULL; -- cgit v1.2.3-70-g09d2 From a9fe592842bfa17d91f4904d7fb0e3af3adebb17 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 8 Jul 2010 15:28:53 +0200 Subject: * apt-pkg/pkgcachegen.{cc,h}: - make the used MMap moveable (and therefore dynamic resizeable) by applying (some) mad pointer magic (Closes: #195018) --- apt-pkg/cacheiterators.h | 6 ++ apt-pkg/contrib/mmap.cc | 27 ++++-- apt-pkg/deb/debindexfile.cc | 1 + apt-pkg/pkgcache.cc | 5 +- apt-pkg/pkgcache.h | 2 +- apt-pkg/pkgcachegen.cc | 229 ++++++++++++++++++++++++++++++++------------ apt-pkg/pkgcachegen.h | 30 ++++-- debian/changelog | 3 + 8 files changed, 226 insertions(+), 77 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index dfe5707e1..eb8dee5e3 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -75,6 +75,12 @@ template class pkgCache::Iterator : inline bool IsGood() const { return S && Owner && ! end();}; inline unsigned long Index() const {return S - OwnerPointer();}; + void ReOwn(pkgCache &newOwner, void const * const oldMap, void const * const newMap) { + if (S == 0) + return; + S += (Str*)(newMap) - (Str*)(oldMap); + } + // Constructors - look out for the variable assigning inline Iterator() : S(0), Owner(0) {}; inline Iterator(pkgCache &Owner,Str *T = 0) : S(T), Owner(&Owner) {}; diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index d71066243..aa184b130 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -225,22 +225,22 @@ DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long const &WorkSpace, // disable Moveable if we don't grow if (Grow == 0) - Flags &= ~Moveable; + this->Flags &= ~Moveable; #ifndef __linux__ // kfreebsd doesn't have mremap, so we use the fallback - if ((Flags & Moveable) == Moveable) - Flags |= Fallback; + if ((this->Flags & Moveable) == Moveable) + this->Flags |= Fallback; #endif #ifdef _POSIX_MAPPED_FILES - if ((Flags & Fallback) != Fallback) { + if ((this->Flags & Fallback) != Fallback) { // Set the permissions. int Prot = PROT_READ; int Map = MAP_PRIVATE | MAP_ANONYMOUS; - if ((Flags & ReadOnly) != ReadOnly) + if ((this->Flags & ReadOnly) != ReadOnly) Prot |= PROT_WRITE; - if ((Flags & Public) == Public) + if ((this->Flags & Public) == Public) Map = MAP_SHARED | MAP_ANONYMOUS; // use anonymous mmap() to get the memory @@ -314,7 +314,7 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) // Look for a matching pool entry Pool *I; Pool *Empty = 0; - for (I = Pools; I != Pools + PoolCount; I++) + for (I = Pools; I != Pools + PoolCount; ++I) { if (I->ItemSize == 0) Empty = I; @@ -342,7 +342,11 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize) { const unsigned long size = 20*1024; I->Count = size/ItemSize; + Pool* oldPools = Pools; Result = RawAllocate(size,ItemSize); + if (Pools != oldPools) + I += Pools - oldPools; + // Does the allocation failed ? if (Result == 0 && _error->PendingError()) return 0; @@ -365,7 +369,7 @@ unsigned long DynamicMMap::WriteString(const char *String, if (Len == (unsigned long)-1) Len = strlen(String); - unsigned long Result = RawAllocate(Len+1,0); + unsigned long const Result = RawAllocate(Len+1,0); if (Result == 0 && _error->PendingError()) return 0; @@ -395,16 +399,20 @@ bool DynamicMMap::Grow() { return _error->Error(_("Unable to increase the size of the MMap as the " "limit of %lu bytes is already reached."), Limit); - unsigned long const newSize = WorkSpace + 1024*1024; + unsigned long const newSize = WorkSpace + GrowFactor; if(Fd != 0) { Fd->Seek(newSize - 1); char C = 0; Fd->Write(&C,sizeof(C)); } + + unsigned long const poolOffset = Pools - ((Pool*) Base); + if ((Flags & Fallback) != Fallback) { #if defined(_POSIX_MAPPED_FILES) && defined(__linux__) #ifdef MREMAP_MAYMOVE + if ((Flags & Moveable) == Moveable) Base = mremap(Base, WorkSpace, newSize, MREMAP_MAYMOVE); else @@ -425,6 +433,7 @@ bool DynamicMMap::Grow() { return false; } + Pools =(Pool*) Base + poolOffset; WorkSpace = newSize; return true; } diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 6d9e99497..5e6db3f38 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -277,6 +277,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const // Store the IMS information pkgCache::PkgFileIterator File = Gen.GetCurFile(); + pkgCacheGenerator::Dynamic DynFile(File); struct stat St; if (fstat(Pkg.Fd(),&St) != 0) return _error->Errno("fstat","Failed to stat"); diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 68aa83d0c..8af8ef7de 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -119,7 +119,7 @@ pkgCache::pkgCache(MMap *Map, bool DoMap) : Map(*Map) // Cache::ReMap - Reopen the cache file /*{{{*/ // --------------------------------------------------------------------- /* If the file is already closed then this will open it open it. */ -bool pkgCache::ReMap() +bool pkgCache::ReMap(bool const &Errorchecks) { // Apply the typecasts. HeaderP = (Header *)Map.Data(); @@ -135,6 +135,9 @@ bool pkgCache::ReMap() StringItemP = (StringItem *)Map.Data(); StrP = (char *)Map.Data(); + if (Errorchecks == false) + return true; + if (Map.Size() == 0 || HeaderP == 0) return _error->Error(_("Empty package cache")); diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 426bb9f13..799521784 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -174,7 +174,7 @@ class pkgCache /*{{{*/ StringItem *StringItemP; char *StrP; - virtual bool ReMap(); + virtual bool ReMap(bool const &Errorchecks = true); inline bool Sync() {return Map.Sync();}; inline MMap &GetMap() {return Map;}; inline void *DataEnd() {return ((unsigned char *)Map.Data()) + Map.Size();}; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 62e457734..18bad6727 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -36,6 +36,7 @@ #include /*}}}*/ typedef vector::iterator FileIterator; +template std::set pkgCacheGenerator::Dynamic::toReMap; // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/ // --------------------------------------------------------------------- @@ -61,8 +62,12 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : // Starting header *Cache.HeaderP = pkgCache::Header(); - Cache.HeaderP->VerSysName = WriteStringInMap(_system->VS->Label); - Cache.HeaderP->Architecture = WriteStringInMap(_config->Find("APT::Architecture")); + map_ptrloc const idxVerSysName = WriteStringInMap(_system->VS->Label); + Cache.HeaderP->VerSysName = idxVerSysName; + map_ptrloc const idxArchitecture = WriteStringInMap(_config->Find("APT::Architecture")); + Cache.HeaderP->Architecture = idxArchitecture; + if (unlikely(idxVerSysName == 0 || idxArchitecture == 0)) + return; Cache.ReMap(); } else @@ -96,19 +101,65 @@ pkgCacheGenerator::~pkgCacheGenerator() Map.Sync(0,sizeof(pkgCache::Header)); } /*}}}*/ +void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap) {/*{{{*/ + if (oldMap == newMap) + return; + + Cache.ReMap(false); + + CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap; + + for (size_t i = 0; i < _count(UniqHash); ++i) + if (UniqHash[i] != 0) + UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap; + + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); + for (std::set::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReOwn(Cache, oldMap, newMap); +} /*}}}*/ // CacheGenerator::WriteStringInMap /*{{{*/ -unsigned long pkgCacheGenerator::WriteStringInMap(const char *String, +map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String, const unsigned long &Len) { - return Map.WriteString(String, Len); + void const * const oldMap = Map.Data(); + map_ptrloc const index = Map.WriteString(String, Len); + if (index != 0) + ReMap(oldMap, Map.Data()); + return index; } /*}}}*/ // CacheGenerator::WriteStringInMap /*{{{*/ -unsigned long pkgCacheGenerator::WriteStringInMap(const char *String) { - return Map.WriteString(String); +map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String) { + void const * const oldMap = Map.Data(); + map_ptrloc const index = Map.WriteString(String); + if (index != 0) + ReMap(oldMap, Map.Data()); + return index; } /*}}}*/ -unsigned long pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/ - return Map.Allocate(size); +map_ptrloc pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/ + void const * const oldMap = Map.Data(); + map_ptrloc const index = Map.Allocate(size); + if (index != 0) + ReMap(oldMap, Map.Data()); + return index; } /*}}}*/ // CacheGenerator::MergeList - Merge the package list /*{{{*/ @@ -142,6 +193,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List, { // Get a pointer to the package structure pkgCache::PkgIterator Pkg; + Dynamic DynPkg(Pkg); if (NewPackage(Pkg, PackageName, *arch) == false) return _error->Error(_("Error occurred while processing %s (NewPackage)"),PackageName.c_str()); Counter++; @@ -158,6 +210,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List, // (this has the bonus that we get MMap error when we run out // of MMap space) pkgCache::VerIterator Ver(Cache); + Dynamic DynVer(Ver); if (List.UsePackage(Pkg, Ver) == false) return _error->Error(_("Error occurred while processing %s (UsePackage1)"), PackageName.c_str()); @@ -165,11 +218,11 @@ bool pkgCacheGenerator::MergeList(ListParser &List, // Find the right version to write the description MD5SumValue CurMd5 = List.Description_md5(); Ver = Pkg.VersionList(); - map_ptrloc *LastVer = &Pkg->VersionList; - for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) + for (; Ver.end() == false; ++Ver) { pkgCache::DescIterator Desc = Ver.DescriptionList(); + Dynamic DynDesc(Desc); map_ptrloc *LastDesc = &Ver->DescriptionList; bool duplicate=false; @@ -189,7 +242,11 @@ bool pkgCacheGenerator::MergeList(ListParser &List, if (MD5SumValue(Desc.md5()) == CurMd5) { // Add new description - *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc); + void const * const oldMap = Map.Data(); + map_ptrloc const descindex = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc); + if (oldMap != Map.Data()) + LastDesc += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; + *LastDesc = descindex; Desc->ParentPkg = Pkg.Index(); if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false) @@ -203,7 +260,9 @@ bool pkgCacheGenerator::MergeList(ListParser &List, } pkgCache::VerIterator Ver = Pkg.VersionList(); + Dynamic DynVer(Ver); map_ptrloc *LastVer = &Pkg->VersionList; + void const * oldMap = Map.Data(); int Res = 1; unsigned long const Hash = List.VersionHash(); for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) @@ -242,21 +301,28 @@ bool pkgCacheGenerator::MergeList(ListParser &List, } // Add a new version - *LastVer = NewVersion(Ver,Version,*LastVer); + map_ptrloc const verindex = NewVersion(Ver,Version,*LastVer); + if (verindex == 0 && _error->PendingError()) + return _error->Error(_("Error occurred while processing %s (NewVersion%d)"), + PackageName.c_str(), 1); + + if (oldMap != Map.Data()) + LastVer += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; + *LastVer = verindex; Ver->ParentPkg = Pkg.Index(); Ver->Hash = Hash; - if ((*LastVer == 0 && _error->PendingError()) || List.NewVersion(Ver) == false) - return _error->Error(_("Error occurred while processing %s (NewVersion1)"), - PackageName.c_str()); + if (List.NewVersion(Ver) == false) + return _error->Error(_("Error occurred while processing %s (NewVersion%d)"), + PackageName.c_str(), 2); if (List.UsePackage(Pkg,Ver) == false) return _error->Error(_("Error occurred while processing %s (UsePackage3)"), PackageName.c_str()); if (NewFileVer(Ver,List) == false) - return _error->Error(_("Error occurred while processing %s (NewVersion2)"), - PackageName.c_str()); + return _error->Error(_("Error occurred while processing %s (NewVersion%d)"), + PackageName.c_str(), 3); // Read only a single record and return if (OutVer != 0) @@ -269,13 +335,18 @@ bool pkgCacheGenerator::MergeList(ListParser &List, /* Record the Description data. Description data always exist in Packages and Translation-* files. */ pkgCache::DescIterator Desc = Ver.DescriptionList(); + Dynamic DynDesc(Desc); map_ptrloc *LastDesc = &Ver->DescriptionList; - + // Skip to the end of description set for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++); // Add new description - *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc); + oldMap = Map.Data(); + map_ptrloc const descindex = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc); + if (oldMap != Map.Data()) + LastDesc += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; + *LastDesc = descindex; Desc->ParentPkg = Pkg.Index(); if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false) @@ -322,6 +393,7 @@ bool pkgCacheGenerator::MergeFileProvides(ListParser &List) continue; pkgCache::PkgIterator Pkg = Cache.FindPkg(PackageName); + Dynamic DynPkg(Pkg); if (Pkg.end() == true) return _error->Error(_("Error occurred while processing %s (FindPkg)"), PackageName.c_str()); @@ -331,6 +403,7 @@ bool pkgCacheGenerator::MergeFileProvides(ListParser &List) unsigned long Hash = List.VersionHash(); pkgCache::VerIterator Ver = Pkg.VersionList(); + Dynamic DynVer(Ver); for (; Ver.end() == false; Ver++) { if (Ver->Hash == Hash && Version.c_str() == Ver.VerStr()) @@ -358,14 +431,15 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name) return true; // Get a structure - unsigned long const Group = AllocateInMap(sizeof(pkgCache::Group)); + map_ptrloc const Group = AllocateInMap(sizeof(pkgCache::Group)); if (unlikely(Group == 0)) return false; Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group); - Grp->Name = WriteStringInMap(Name); - if (unlikely(Grp->Name == 0)) + map_ptrloc const idxName = WriteStringInMap(Name); + if (unlikely(idxName == 0)) return false; + Grp->Name = idxName; // Insert it into the hash table unsigned long const Hash = Cache.Hash(Name); @@ -382,6 +456,7 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name) bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name, const string &Arch) { pkgCache::GrpIterator Grp; + Dynamic DynGrp(Grp); if (unlikely(NewGroup(Grp, Name) == false)) return false; @@ -390,7 +465,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name return true; // Get a structure - unsigned long const Package = AllocateInMap(sizeof(pkgCache::Package)); + map_ptrloc const Package = AllocateInMap(sizeof(pkgCache::Package)); if (unlikely(Package == 0)) return false; Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package); @@ -416,9 +491,10 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name // Set the name, arch and the ID Pkg->Name = Grp->Name; Pkg->Group = Grp.Index(); - Pkg->Arch = WriteUniqString(Arch.c_str()); - if (unlikely(Pkg->Arch == 0)) + map_ptrloc const idxArch = WriteUniqString(Arch.c_str()); + if (unlikely(idxArch == 0)) return false; + Pkg->Arch = idxArch; Pkg->ID = Cache.HeaderP->PackageCount++; return true; @@ -434,7 +510,7 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver, return true; // Get a structure - unsigned long VerFile = AllocateInMap(sizeof(pkgCache::VerFile)); + map_ptrloc const VerFile = AllocateInMap(sizeof(pkgCache::VerFile)); if (VerFile == 0) return 0; @@ -465,7 +541,7 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, unsigned long Next) { // Get a structure - unsigned long Version = AllocateInMap(sizeof(pkgCache::Version)); + map_ptrloc const Version = AllocateInMap(sizeof(pkgCache::Version)); if (Version == 0) return 0; @@ -473,9 +549,10 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version); Ver->NextVer = Next; Ver->ID = Cache.HeaderP->VersionCount++; - Ver->VerStr = WriteStringInMap(VerStr); - if (Ver->VerStr == 0) + map_ptrloc const idxVerStr = WriteStringInMap(VerStr); + if (unlikely(idxVerStr == 0)) return 0; + Ver->VerStr = idxVerStr; return Version; } @@ -490,7 +567,7 @@ bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc, return true; // Get a structure - unsigned long DescFile = AllocateInMap(sizeof(pkgCache::DescFile)); + map_ptrloc const DescFile = AllocateInMap(sizeof(pkgCache::DescFile)); if (DescFile == 0) return false; @@ -523,7 +600,7 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, map_ptrloc Next) { // Get a structure - map_ptrloc Description = AllocateInMap(sizeof(pkgCache::Description)); + map_ptrloc const Description = AllocateInMap(sizeof(pkgCache::Description)); if (Description == 0) return 0; @@ -531,10 +608,12 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description); Desc->NextDesc = Next; Desc->ID = Cache.HeaderP->DescriptionCount++; - Desc->language_code = WriteStringInMap(Lang); - Desc->md5sum = WriteStringInMap(md5sum.Value()); - if (Desc->language_code == 0 || Desc->md5sum == 0) + map_ptrloc const idxlanguage_code = WriteStringInMap(Lang); + map_ptrloc const idxmd5sum = WriteStringInMap(md5sum.Value()); + if (unlikely(idxlanguage_code == 0 || idxmd5sum == 0)) return 0; + Desc->language_code = idxlanguage_code; + Desc->md5sum = idxmd5sum; return Description; } @@ -550,15 +629,22 @@ bool pkgCacheGenerator::FinishCache(OpProgress *Progress) if (archs.size() > 1) { // Create Conflicts in between the group - for (pkgCache::GrpIterator G = GetCache().GrpBegin(); G.end() != true; G++) + pkgCache::GrpIterator G = GetCache().GrpBegin(); + Dynamic DynG(G); + for (; G.end() != true; G++) { string const PkgName = G.Name(); - for (pkgCache::PkgIterator P = G.PackageList(); P.end() != true; P = G.NextPkg(P)) + pkgCache::PkgIterator P = G.PackageList(); + Dynamic DynP(P); + for (; P.end() != true; P = G.NextPkg(P)) { if (strcmp(P.Arch(),"all") == 0) continue; pkgCache::PkgIterator allPkg; - for (pkgCache::VerIterator V = P.VersionList(); V.end() != true; V++) + Dynamic DynallPkg(allPkg); + pkgCache::VerIterator V = P.VersionList(); + Dynamic DynV(V); + for (; V.end() != true; V++) { string const Arch = V.Arch(true); map_ptrloc *OldDepLast = NULL; @@ -578,6 +664,7 @@ bool pkgCacheGenerator::FinishCache(OpProgress *Progress) per group, therefore each group member conflicts with all other group members */ pkgCache::PkgIterator D = G.FindPkg(*A); + Dynamic DynD(D); if (D.end() == true) continue; if (coInstall == true) @@ -622,13 +709,15 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, unsigned int const &Type, map_ptrloc *OldDepLast) { + void const * const oldMap = Map.Data(); // Get a structure - unsigned long const Dependency = AllocateInMap(sizeof(pkgCache::Dependency)); + map_ptrloc const Dependency = AllocateInMap(sizeof(pkgCache::Dependency)); if (unlikely(Dependency == 0)) return false; // Fill it in pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency); + Dynamic DynDep(Dep); Dep->ParentVer = Ver.Index(); Dep->Type = Type; Dep->CompareOp = Op; @@ -640,9 +729,12 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, /* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++) if (I->Version != 0 && I.TargetVer() == Version) Dep->Version = I->Version;*/ - if (Dep->Version == 0) - if (unlikely((Dep->Version = WriteStringInMap(Version)) == 0)) + if (Dep->Version == 0) { + map_ptrloc const index = WriteStringInMap(Version); + if (unlikely(index == 0)) return false; + Dep->Version = index; + } } // Link it to the package @@ -656,7 +748,8 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, OldDepLast = &Ver->DependsList; for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++) OldDepLast = &D->NextDepends; - } + } else if (oldMap != Map.Data()) + OldDepLast += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; Dep->NextDepends = *OldDepLast; *OldDepLast = Dep.Index(); @@ -677,11 +770,13 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, unsigned int Type) { pkgCache::GrpIterator Grp; + Dynamic DynGrp(Grp); if (unlikely(Owner->NewGroup(Grp, PackageName) == false)) return false; // Locate the target package pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch); + Dynamic DynPkg(Pkg); if (Pkg.end() == true) { if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false)) return false; @@ -715,13 +810,14 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, return true; // Get a structure - unsigned long const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides)); + map_ptrloc const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides)); if (unlikely(Provides == 0)) return false; Cache.HeaderP->ProvidesCount++; // Fill it in pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP); + Dynamic DynPrv(Prv); Prv->Version = Ver.Index(); Prv->NextPkgProv = Ver->ProvidesList; Ver->ProvidesList = Prv.Index(); @@ -730,6 +826,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, // Locate the target package pkgCache::PkgIterator Pkg; + Dynamic DynPkg(Pkg); if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false)) return false; @@ -750,24 +847,29 @@ bool pkgCacheGenerator::SelectFile(const string &File,const string &Site, unsigned long Flags) { // Get some space for the structure - CurrentFile = Cache.PkgFileP + AllocateInMap(sizeof(*CurrentFile)); - if (CurrentFile == Cache.PkgFileP) + map_ptrloc const idxFile = AllocateInMap(sizeof(*CurrentFile)); + if (unlikely(idxFile == 0)) return false; - + CurrentFile = Cache.PkgFileP + idxFile; + // Fill it in - CurrentFile->FileName = WriteStringInMap(File); - CurrentFile->Site = WriteUniqString(Site); + map_ptrloc const idxFileName = WriteStringInMap(File); + map_ptrloc const idxSite = WriteUniqString(Site); + if (unlikely(idxFileName == 0 || idxSite == 0)) + return false; + CurrentFile->FileName = idxFileName; + CurrentFile->Site = idxSite; CurrentFile->NextFile = Cache.HeaderP->FileList; CurrentFile->Flags = Flags; CurrentFile->ID = Cache.HeaderP->PackageFileCount; - CurrentFile->IndexType = WriteUniqString(Index.GetType()->Label); + map_ptrloc const idxIndexType = WriteUniqString(Index.GetType()->Label); + if (unlikely(idxIndexType == 0)) + return false; + CurrentFile->IndexType = idxIndexType; PkgFileName = File; Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP; Cache.HeaderP->PackageFileCount++; - if (CurrentFile->FileName == 0) - return false; - if (Progress != 0) Progress->SubProgress(Index.Size()); return true; @@ -807,18 +909,25 @@ unsigned long pkgCacheGenerator::WriteUniqString(const char *S, } // Get a structure - unsigned long Item = AllocateInMap(sizeof(pkgCache::StringItem)); + void const * const oldMap = Map.Data(); + map_ptrloc const Item = AllocateInMap(sizeof(pkgCache::StringItem)); if (Item == 0) return 0; + map_ptrloc const idxString = WriteStringInMap(S,Size); + if (unlikely(idxString == 0)) + return 0; + if (oldMap != Map.Data()) { + Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; + I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap; + } + *Last = Item; + // Fill in the structure pkgCache::StringItem *ItemP = Cache.StringItemP + Item; ItemP->NextItem = I - Cache.StringItemP; - *Last = Item; - ItemP->String = WriteStringInMap(S,Size); - if (ItemP->String == 0) - return 0; - + ItemP->String = idxString; + Bucket = ItemP; return ItemP->String; } @@ -1072,7 +1181,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress unlink(CacheFile.c_str()); CacheF = new FileFd(CacheFile,FileFd::WriteEmpty); fchmod(CacheF->Fd(),0644); - Map = new DynamicMMap(*CacheF,MMap::Public,MapSize); + Map = new DynamicMMap(*CacheF,MMap::Public | MMap::Moveable, MapSize); if (_error->PendingError() == true) return false; if (Debug == true) @@ -1081,7 +1190,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress else { // Just build it in memory.. - Map = new DynamicMMap(0,MapSize); + Map = new DynamicMMap(MMap::Moveable, MapSize); if (Debug == true) std::clog << "Open memory Map (not filebased)" << std::endl; } @@ -1194,7 +1303,7 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O if (_system->AddStatusFiles(Files) == false) return false; - SPtr Map = new DynamicMMap(0,MapSize); + SPtr Map = new DynamicMMap(MMap::Moveable, MapSize); unsigned long CurrentSize = 0; unsigned long TotalSize = 0; diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 8f7739165..3bee1f958 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -23,6 +23,8 @@ #include #include +#include + class pkgSourceList; class OpProgress; class MMap; @@ -33,18 +35,32 @@ class pkgCacheGenerator /*{{{*/ private: pkgCache::StringItem *UniqHash[26]; - unsigned long WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); }; - unsigned long WriteStringInMap(const char *String); - unsigned long WriteStringInMap(const char *String, const unsigned long &Len); - unsigned long AllocateInMap(const unsigned long &size); + map_ptrloc WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); }; + map_ptrloc WriteStringInMap(const char *String); + map_ptrloc WriteStringInMap(const char *String, const unsigned long &Len); + map_ptrloc AllocateInMap(const unsigned long &size); public: class ListParser; friend class ListParser; - + + template class Dynamic { + Iter *I; + + public: + static std::set toReMap; + Dynamic(Iter &It) : I(&It) { + toReMap.insert(I); + } + + ~Dynamic() { + toReMap.erase(I); + } + }; + protected: - + DynamicMMap ⤅ pkgCache Cache; OpProgress *Progress; @@ -86,6 +102,8 @@ class pkgCacheGenerator /*{{{*/ MMap **OutMap = 0,bool AllowMem = false); static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap); + void ReMap(void const * const oldMap, void const * const newMap); + pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress); ~pkgCacheGenerator(); }; diff --git a/debian/changelog b/debian/changelog index 878d5238a..dab703c6b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -37,6 +37,9 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/policy.h: - add another round of const& madness as the previous round accidentally NOT overrides the virtual GetCandidateVer() method (Closes: #587725) + * apt-pkg/pkgcachegen.{cc,h}: + - make the used MMap moveable (and therefore dynamic resizeable) by + applying (some) mad pointer magic (Closes: #195018) [ Julian Andres Klode ] * methods/ftp.h: -- cgit v1.2.3-70-g09d2 From dcdf1ef18b37c243fc707869149f7761d964915c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 9 Jul 2010 17:00:28 +0200 Subject: * doc/apt.conf.5.xml: - add and document APT::Cache-{Start,Grow,Limit} options for mmap control --- apt-pkg/contrib/mmap.cc | 2 ++ apt-pkg/pkgcachegen.cc | 22 ++++++++++++++++------ apt-pkg/pkgcachegen.h | 1 + debian/changelog | 4 +++- doc/apt.conf.5.xml | 17 ++++++++++++++--- doc/examples/configure-index | 4 +++- 6 files changed, 39 insertions(+), 11 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/mmap.cc b/apt-pkg/contrib/mmap.cc index aa184b130..69fb61fca 100644 --- a/apt-pkg/contrib/mmap.cc +++ b/apt-pkg/contrib/mmap.cc @@ -398,6 +398,8 @@ bool DynamicMMap::Grow() { if (Limit != 0 && WorkSpace >= Limit) return _error->Error(_("Unable to increase the size of the MMap as the " "limit of %lu bytes is already reached."), Limit); + if (GrowFactor <= 0) + return _error->Error(_("Unable to increase size of the MMap as automatic growing is disabled by user.")); unsigned long const newSize = WorkSpace + GrowFactor; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 18bad6727..7ca8fbfda 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -1094,6 +1094,18 @@ static bool BuildCache(pkgCacheGenerator &Gen, return true; } /*}}}*/ +DynamicMMap* pkgCacheGenerator::CreateDynamicMMap(FileFd *CacheF, unsigned long Flags) { + unsigned long const MapStart = _config->FindI("APT::Cache-Start", 24*1024*1024); + unsigned long const MapGrow = _config->FindI("APT::Cache-Grow", 1*1024*1024); + unsigned long const MapLimit = _config->FindI("APT::Cache-Limit", 0); + Flags |= MMap::Moveable; + if (_config->FindB("APT::Cache-Fallback", false) == true) + Flags |= MMap::Fallback; + if (CacheF != NULL) + return new DynamicMMap(*CacheF, Flags, MapStart, MapGrow, MapLimit); + else + return new DynamicMMap(Flags, MapStart, MapGrow, MapLimit); +} // CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/ // --------------------------------------------------------------------- /* This makes sure that the status cache (the cache that has all @@ -1109,7 +1121,6 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress MMap **OutMap,bool AllowMem) { bool const Debug = _config->FindB("Debug::pkgCacheGen", false); - unsigned long const MapSize = _config->FindI("APT::Cache-Limit",24*1024*1024); vector Files; for (vector::const_iterator i = List.begin(); @@ -1181,7 +1192,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress unlink(CacheFile.c_str()); CacheF = new FileFd(CacheFile,FileFd::WriteEmpty); fchmod(CacheF->Fd(),0644); - Map = new DynamicMMap(*CacheF,MMap::Public | MMap::Moveable, MapSize); + Map = CreateDynamicMMap(CacheF, MMap::Public); if (_error->PendingError() == true) return false; if (Debug == true) @@ -1190,7 +1201,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress else { // Just build it in memory.. - Map = new DynamicMMap(MMap::Moveable, MapSize); + Map = CreateDynamicMMap(NULL); if (Debug == true) std::clog << "Open memory Map (not filebased)" << std::endl; } @@ -1297,13 +1308,12 @@ __deprecated bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutM { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress, OutMap); } bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap) { - unsigned long MapSize = _config->FindI("APT::Cache-Limit",20*1024*1024); vector Files; unsigned long EndOfSource = Files.size(); if (_system->AddStatusFiles(Files) == false) return false; - - SPtr Map = new DynamicMMap(MMap::Moveable, MapSize); + + SPtr Map = CreateDynamicMMap(NULL); unsigned long CurrentSize = 0; unsigned long TotalSize = 0; diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 3bee1f958..20dd28030 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -101,6 +101,7 @@ class pkgCacheGenerator /*{{{*/ static bool MakeStatusCache(pkgSourceList &List,OpProgress *Progress, MMap **OutMap = 0,bool AllowMem = false); static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap); + static DynamicMMap* CreateDynamicMMap(FileFd *CacheF, unsigned long Flags = 0); void ReMap(void const * const oldMap, void const * const newMap); diff --git a/debian/changelog b/debian/changelog index dab703c6b..f819908ad 100644 --- a/debian/changelog +++ b/debian/changelog @@ -40,6 +40,8 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * apt-pkg/pkgcachegen.{cc,h}: - make the used MMap moveable (and therefore dynamic resizeable) by applying (some) mad pointer magic (Closes: #195018) + * doc/apt.conf.5.xml: + - add and document APT::Cache-{Start,Grow,Limit} options for mmap control [ Julian Andres Klode ] * methods/ftp.h: @@ -55,7 +57,7 @@ apt (0.7.26~exp8) UNRELEASED; urgency=low * debian/control: - Set Standards-Version to 3.9.0 - -- David Kalnischkies Mon, 05 Jul 2010 12:05:30 +0200 + -- David Kalnischkies Fri, 09 Jul 2010 16:55:53 +0200 apt (0.7.26~exp7) experimental; urgency=low diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index 39e2c8e6b..7b7290794 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -199,9 +199,20 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; anything that those packages depend on. - Cache-Limit - APT uses a fixed size memory mapped cache file to store the 'available' - information. This sets the size of that cache (in bytes). + Cache-Start, Cache-Grow and Cache-Limit + APT uses since version 0.7.26 a resizable memory mapped cache file to store the 'available' + information. Cache-Start acts as a hint to which size the Cache will grow + and is therefore the amount of memory APT will request at startup. The default value is + 20971520 bytes (~20 MB). Note that these amount of space need to be available for APT + otherwise it will likely fail ungracefully, so for memory restricted devices these value should + be lowered while on systems with a lot of configured sources this might be increased. + Cache-Grow defines in byte with the default of 1048576 (~1 MB) how much + the Cache size will be increased in the event the space defined by Cache-Start + is not enough. These value will be applied again and again until either the cache is big + enough to store all information or the size of the cache reaches the Cache-Limit. + The default of Cache-Limit is 0 which stands for no limit. + If Cache-Grow is set to 0 the automatic grow of the cache is disabled. + Build-Essential diff --git a/doc/examples/configure-index b/doc/examples/configure-index index fdec32c2c..26fb53fec 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -95,7 +95,9 @@ APT Clean-Installed "true"; Immediate-Configure "true"; // DO NOT turn this off, see the man page Force-LoopBreak "false"; // DO NOT turn this on, see the man page - Cache-Limit "4194304"; + Cache-Start "20971520"; + Cache-Grow "1048576"; + Cache-Limit "0"; Default-Release ""; // consider Recommends, Suggests as important dependencies that should -- cgit v1.2.3-70-g09d2 From 62d073d937742baf8621a11c3094e0320aa846cd Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 9 Jul 2010 21:46:42 +0200 Subject: check the state of the FileFd before renaming as otherwise the rename will be tried twice e.g. in an "apt-get update" run and every other piece of code closing the FileFd manual before the destructor will do it again. --- apt-pkg/contrib/fileutl.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 62d42e4da..8f7791a8a 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -843,19 +843,21 @@ bool FileFd::Close() bool Res = true; if ((Flags & AutoClose) == AutoClose) if (iFd >= 0 && close(iFd) != 0) - Res &= _error->Errno("close",_("Problem closing the file")); - iFd = -1; + Res &= _error->Errno("close",_("Problem closing the file %s"), FileName.c_str()); - if ((Flags & Replace) == Replace) { + if ((Flags & Replace) == Replace && iFd >= 0) { if (rename(TemporaryFileName.c_str(), FileName.c_str()) != 0) - Res &= _error->Errno("rename",_("Problem renaming the file")); + Res &= _error->Errno("rename",_("Problem renaming the file %s to %s"), TemporaryFileName.c_str(), FileName.c_str()); + FileName = TemporaryFileName; // for the unlink() below. } - + + iFd = -1; + if ((Flags & Fail) == Fail && (Flags & DelOnFail) == DelOnFail && FileName.empty() == false) if (unlink(FileName.c_str()) != 0) - Res &= _error->WarningE("unlnk",_("Problem unlinking the file")); + Res &= _error->WarningE("unlnk",_("Problem unlinking the file %s"), FileName.c_str()); return Res; -- cgit v1.2.3-70-g09d2 From 3c0929ecbeab50de9d38edc2eaebe92aeee65baf Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 10 Jul 2010 13:51:47 +0200 Subject: * apt-pkg/contrib/error.{cc,h}: - remove constness of va_list parameter to fix build on amd64 and co Thanks Eric Valette! (Closes: #588610) --- apt-pkg/contrib/error.cc | 9 ++++----- apt-pkg/contrib/error.h | 4 ++-- debian/changelog | 9 +++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc index 8cee21c9c..fbb6e4636 100644 --- a/apt-pkg/contrib/error.cc +++ b/apt-pkg/contrib/error.cc @@ -94,11 +94,10 @@ bool GlobalError::DebugE(const char *Function,const char *Description,...) { /*}}}*/ // GlobalError::InsertErrno - formats an error message with the errno /*{{{*/ bool GlobalError::InsertErrno(MsgType type, const char* Function, - const char* Description, va_list const &args) { + const char* Description, va_list &args) { char S[400]; - vsnprintf(S,sizeof(S),Description,args); - snprintf(S + strlen(S),sizeof(S) - strlen(S), - " - %s (%i: %s)", Function, errno, strerror(errno)); + snprintf(S, sizeof(S), "%s - %s (%i: %s)", Description, + Function, errno, strerror(errno)); return Insert(type, S, args); } /*}}}*/ @@ -141,7 +140,7 @@ bool GlobalError::Debug(const char *Description,...) /*}}}*/ // GlobalError::Insert - Insert a new item at the end /*{{{*/ bool GlobalError::Insert(MsgType type, const char* Description, - va_list const &args) { + va_list &args) { char S[400]; vsnprintf(S,sizeof(S),Description,args); diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index 73735162d..e5517c2da 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -278,9 +278,9 @@ private: /*{{{*/ std::list Stacks; bool InsertErrno(MsgType type, const char* Function, - const char* Description, va_list const &args); + const char* Description, va_list &args); bool Insert(MsgType type, const char* Description, - va_list const &args); + va_list &args); /*}}}*/ }; /*}}}*/ diff --git a/debian/changelog b/debian/changelog index a4ee9a7f8..23a5f9351 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +apt (0.7.26~exp10) UNRELEASED; urgency=low + + [ David Kalnischkies ] + * apt-pkg/contrib/error.{cc,h}: + - remove constness of va_list parameter to fix build on amd64 and co + Thanks Eric Valette! (Closes: #588610) + + -- David Kalnischkies Sat, 10 Jul 2010 13:44:32 +0200 + apt (0.7.26~exp9) experimental; urgency=low [ David Kalnischkies ] -- cgit v1.2.3-70-g09d2 From 144c096976b2ce05fe64e5761c0df5854f6c0c09 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 23 Jul 2010 16:13:15 +0200 Subject: * apt-pkg/contrib/fileutl.cc: - Add FileFd::OpenDescriptor() (needed for python-apt's #383617). --- apt-pkg/contrib/fileutl.cc | 18 ++++++++++++++++++ apt-pkg/contrib/fileutl.h | 4 ++++ debian/changelog | 2 ++ 3 files changed, 24 insertions(+) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 49b2f3828..2a3b8a87d 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -700,6 +700,24 @@ bool FileFd::Open(string FileName,OpenMode Mode, unsigned long Perms) SetCloseExec(iFd,true); return true; } + +bool FileFd::OpenDescriptor(int Fd, OpenMode Mode, bool AutoClose) +{ + Close(); + Flags = (AutoClose) ? FileFd::AutoClose : 0; + iFd = Fd; + if (Mode == ReadOnlyGzip) { + gz = gzdopen (iFd, "r"); + if (gz == NULL) { + if (AutoClose) + close (iFd); + return _error->Errno("gzdopen",_("Could not open file descriptor %d"), + Fd); + } + } + this->FileName = ""; + return true; +} /*}}}*/ // FileFd::~File - Closes the file /*{{{*/ // --------------------------------------------------------------------- diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 0f70ab722..62705478d 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -28,6 +28,9 @@ #include +/* Define this for python-apt */ +#define APT_HAS_GZIP 1 + using std::string; class FileFd @@ -60,6 +63,7 @@ class FileFd unsigned long Tell(); unsigned long Size(); bool Open(string FileName,OpenMode Mode,unsigned long Perms = 0666); + bool OpenDescriptor(int Fd, OpenMode Mode, bool AutoClose=false); bool Close(); bool Sync(); diff --git a/debian/changelog b/debian/changelog index 311833192..06454cd5a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,8 @@ apt (0.7.26~exp11) experimental; urgency=low * apt-pkg/deb/dpkgpm.cc: - Write architecture information to history file. - Add to history whether a change was automatic or not. + * apt-pkg/contrib/fileutl.cc: + - Add FileFd::OpenDescriptor() (needed for python-apt's #383617). -- Julian Andres Klode Wed, 21 Jul 2010 17:09:11 +0200 -- cgit v1.2.3-70-g09d2 From 12be8a62d1abb9253a4695badbf70e7210f9b0d2 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 29 Jul 2010 14:37:36 +0200 Subject: * apt-pkg/contrib/error.{cc,h} - docstring cleanup --- apt-pkg/contrib/error.cc | 4 ++-- apt-pkg/contrib/error.h | 11 ++++++----- debian/changelog | 4 ++++ 3 files changed, 12 insertions(+), 7 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc index fbb6e4636..d63b06d13 100644 --- a/apt-pkg/contrib/error.cc +++ b/apt-pkg/contrib/error.cc @@ -180,7 +180,7 @@ bool GlobalError::PopMessage(std::string &Text) { } /*}}}*/ // GlobalError::DumpErrors - Dump all of the errors/warns to cerr /*{{{*/ -void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold, +void GlobalError::DumpErrors(std::ostream &out, MsgType const &threshold, bool const &mergeStack) { if (mergeStack == true) for (std::list::const_reverse_iterator s = Stacks.rbegin(); @@ -189,7 +189,7 @@ void GlobalError::DumpErrors(std::ostream &out, MsgType const &trashhold, for (std::list::const_iterator m = Messages.begin(); m != Messages.end(); m++) - if (m->Type >= trashhold) + if (m->Type >= threshold) out << (*m) << std::endl; Discard(); } diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index e5517c2da..d39500427 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -204,9 +204,10 @@ public: /*{{{*/ * displayed or not. * * \param[out] out output stream to write the messages in - * \param WithoutNotice output notices or not + * \param threshold minimim level considered + * \param mergeStack */ - void DumpErrors(std::ostream &out, MsgType const &trashhold = WARNING, + void DumpErrors(std::ostream &out, MsgType const &threshold = WARNING, bool const &mergeStack = true); /** \brief dumps the list of messages to std::cerr @@ -214,10 +215,10 @@ public: /*{{{*/ * Note that all messages are discarded, also the notices * displayed or not. * - * \param WithoutNotice print notices or not + * \param threshold minimum level printed */ - void inline DumpErrors(MsgType const &trashhold = WARNING) { - DumpErrors(std::cerr, trashhold); + void inline DumpErrors(MsgType const &threshold = WARNING) { + DumpErrors(std::cerr, threshold); } /** \brief put the current Messages into the stack diff --git a/debian/changelog b/debian/changelog index 49f8bce46..545703603 100644 --- a/debian/changelog +++ b/debian/changelog @@ -31,6 +31,10 @@ apt (0.7.26~exp11) experimental; urgency=low - try to install another or-group member in DepRemove before breaking the or group (Closes: #590438) - configure also the replacement before remove by adding Immediate flag + + [ Michael Vogt ] + * apt-pkg/contrib/error.{cc,h} + - docstring cleanup -- David Kalnischkies Mon, 26 Jul 2010 12:40:44 +0200 -- cgit v1.2.3-70-g09d2 From ca0d389c8969ddb679358ca16e4bcddfcdaf9b03 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 29 Jul 2010 14:51:05 +0200 Subject: add inline DumpError() to avoid subtle API break --- apt-pkg/contrib/error.h | 14 +++++++++++++- debian/changelog | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index d39500427..4af0302c0 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -217,10 +217,22 @@ public: /*{{{*/ * * \param threshold minimum level printed */ - void inline DumpErrors(MsgType const &threshold = WARNING) { + void inline DumpErrors(MsgType const &threshold) { DumpErrors(std::cerr, threshold); } + // mvo: we do this instead of using a default parameter in the + // previous declaration to avoid a (subtle) API break for + // e.g. sigc++ and mem_fun0 + /** \brief dumps the messages of type WARNING or higher to std::cerr + * + * Note that all messages are discarded, displayed or not. + * + */ + void inline DumpErrors() { + DumpErrors(WARNING); + } + /** \brief put the current Messages into the stack * * All "old" messages will be pushed into a stack to diff --git a/debian/changelog b/debian/changelog index 545703603..c526df66c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -35,6 +35,7 @@ apt (0.7.26~exp11) experimental; urgency=low [ Michael Vogt ] * apt-pkg/contrib/error.{cc,h} - docstring cleanup + - add inline DumpError() to avoid subtle API break -- David Kalnischkies Mon, 26 Jul 2010 12:40:44 +0200 -- cgit v1.2.3-70-g09d2 From cd7bbc479f8e2f277092a9557bb486ab664deba6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 30 Jul 2010 09:51:42 +0200 Subject: - [ABI BREAK] add an ErrorType option to CacheSetHelper * cmdline/apt-cache.cc: - use Notice instead of Error in the CacheSetHelper messages for compat reasons. Otherwise tools like sbuild blow up --- apt-pkg/cacheset.cc | 18 +++++++++--------- apt-pkg/cacheset.h | 16 +++++++++++++++- apt-pkg/contrib/error.cc | 16 ++++++++++++++++ apt-pkg/contrib/error.h | 16 ++++++++++++++++ cmdline/apt-cache.cc | 24 ++++++++++++++++-------- debian/changelog | 14 +++++++++----- 6 files changed, 81 insertions(+), 23 deletions(-) (limited to 'apt-pkg/contrib') diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 84021a2b7..bbfdfd4f2 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -437,21 +437,21 @@ pkgCache::VerIterator VersionSet::getInstalledVer(pkgCacheFile &Cache, pkgCache::PkgIterator CacheSetHelper::canNotFindPkgName(pkgCacheFile &Cache, std::string const &str) { if (ShowError == true) - _error->Error(_("Unable to locate package %s"), str.c_str()); + _error->Insert(ErrorType, _("Unable to locate package %s"), str.c_str()); return pkgCache::PkgIterator(Cache, 0); } /*}}}*/ // canNotFindTask - handle the case no package is found for a task /*{{{*/ PackageSet CacheSetHelper::canNotFindTask(pkgCacheFile &Cache, std::string pattern) { if (ShowError == true) - _error->Error(_("Couldn't find task '%s'"), pattern.c_str()); + _error->Insert(ErrorType, _("Couldn't find task '%s'"), pattern.c_str()); return PackageSet(); } /*}}}*/ // canNotFindRegEx - handle the case no package is found by a regex /*{{{*/ PackageSet CacheSetHelper::canNotFindRegEx(pkgCacheFile &Cache, std::string pattern) { if (ShowError == true) - _error->Error(_("Couldn't find any package by regex '%s'"), pattern.c_str()); + _error->Insert(ErrorType, _("Couldn't find any package by regex '%s'"), pattern.c_str()); return PackageSet(); } /*}}}*/ @@ -464,7 +464,7 @@ PackageSet CacheSetHelper::canNotFindPackage(pkgCacheFile &Cache, std::string co VersionSet CacheSetHelper::canNotFindAllVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { if (ShowError == true) - _error->Notice(_("Can't select versions from package '%s' as it purely virtual"), Pkg.FullName(true).c_str()); + _error->Insert(ErrorType, _("Can't select versions from package '%s' as it purely virtual"), Pkg.FullName(true).c_str()); return VersionSet(); } /*}}}*/ @@ -472,7 +472,7 @@ VersionSet CacheSetHelper::canNotFindAllVer(pkgCacheFile &Cache, VersionSet CacheSetHelper::canNotFindInstCandVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { if (ShowError == true) - _error->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg.FullName(true).c_str()); + _error->Insert(ErrorType, _("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg.FullName(true).c_str()); return VersionSet(); } /*}}}*/ @@ -480,7 +480,7 @@ VersionSet CacheSetHelper::canNotFindInstCandVer(pkgCacheFile &Cache, VersionSet CacheSetHelper::canNotFindCandInstVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { if (ShowError == true) - _error->Error(_("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg.FullName(true).c_str()); + _error->Insert(ErrorType, _("Can't select installed nor candidate version from package '%s' as it has neither of them"), Pkg.FullName(true).c_str()); return VersionSet(); } /*}}}*/ @@ -488,7 +488,7 @@ VersionSet CacheSetHelper::canNotFindCandInstVer(pkgCacheFile &Cache, pkgCache::VerIterator CacheSetHelper::canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { if (ShowError == true) - _error->Error(_("Can't select newest version from package '%s' as it is purely virtual"), Pkg.FullName(true).c_str()); + _error->Insert(ErrorType, _("Can't select newest version from package '%s' as it is purely virtual"), Pkg.FullName(true).c_str()); return pkgCache::VerIterator(Cache, 0); } /*}}}*/ @@ -496,7 +496,7 @@ pkgCache::VerIterator CacheSetHelper::canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::VerIterator CacheSetHelper::canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { if (ShowError == true) - _error->Error(_("Can't select candidate version from package %s as it has no candidate"), Pkg.FullName(true).c_str()); + _error->Insert(ErrorType, _("Can't select candidate version from package %s as it has no candidate"), Pkg.FullName(true).c_str()); return pkgCache::VerIterator(Cache, 0); } /*}}}*/ @@ -504,7 +504,7 @@ pkgCache::VerIterator CacheSetHelper::canNotFindCandidateVer(pkgCacheFile &Cache pkgCache::VerIterator CacheSetHelper::canNotFindInstalledVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { if (ShowError == true) - _error->Error(_("Can't select installed version from package %s as it is not installed"), Pkg.FullName(true).c_str()); + _error->Insert(ErrorType, _("Can't select installed version from package %s as it is not installed"), Pkg.FullName(true).c_str()); return pkgCache::VerIterator(Cache, 0); } /*}}}*/ diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index c8c3dd096..3f4f0066b 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -32,7 +32,9 @@ class CacheSetHelper { /*{{{*/ printed out. */ public: /*{{{*/ - CacheSetHelper(bool const &ShowError = true) : ShowError(ShowError) {}; + CacheSetHelper(bool const &ShowError = true, + GlobalError::MsgType ErrorType = GlobalError::ERROR) : + ShowError(ShowError), ErrorType(ErrorType) {}; virtual ~CacheSetHelper() {}; virtual void showTaskSelection(PackageSet const &pkgset, string const &pattern) {}; @@ -58,9 +60,21 @@ public: /*{{{*/ bool showErrors() const { return ShowError; }; bool showErrors(bool const &newValue) { if (ShowError == newValue) return ShowError; else return ((ShowError = newValue) == false); }; + GlobalError::MsgType errorType() const { return ErrorType; }; + GlobalError::MsgType errorType(GlobalError::MsgType const &newValue) + { + if (ErrorType == newValue) return ErrorType; + else { + GlobalError::MsgType const &oldValue = ErrorType; + ErrorType = newValue; + return oldValue; + } + }; + /*}}}*/ protected: bool ShowError; + GlobalError::MsgType ErrorType; }; /*}}}*/ class PackageSet : public std::set { /*{{{*/ /** \class APT::PackageSet diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc index d63b06d13..e2e8d6e57 100644 --- a/apt-pkg/contrib/error.cc +++ b/apt-pkg/contrib/error.cc @@ -92,6 +92,14 @@ bool GlobalError::DebugE(const char *Function,const char *Description,...) { return InsertErrno(DEBUG, Function, Description, args); } /*}}}*/ +// GlobalError::InsertErrno - Get part of the errortype string from errno/*{{{*/ +bool GlobalError::InsertErrno(MsgType const &type, const char *Function, + const char *Description,...) { + va_list args; + va_start(args,Description); + return InsertErrno(type, Function, Description, args); +} + /*}}}*/ // GlobalError::InsertErrno - formats an error message with the errno /*{{{*/ bool GlobalError::InsertErrno(MsgType type, const char* Function, const char* Description, va_list &args) { @@ -138,6 +146,14 @@ bool GlobalError::Debug(const char *Description,...) return Insert(DEBUG, Description, args); } /*}}}*/ +// GlobalError::Insert - Add a errotype message to the list /*{{{*/ +bool GlobalError::Insert(MsgType const &type, const char *Description,...) +{ + va_list args; + va_start(args,Description); + return Insert(type, Description, args); +} + /*}}}*/ // GlobalError::Insert - Insert a new item at the end /*{{{*/ bool GlobalError::Insert(MsgType type, const char* Description, va_list &args) { diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index 4af0302c0..ae756dbc4 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -114,6 +114,15 @@ public: /*{{{*/ */ bool DebugE(const char *Function,const char *Description,...) __like_printf(3) __cold; + /** \brief adds an errno message with the given type + * + * \param type of the error message + * \param Function which failed + * \param Description of the error + */ + bool InsertErrno(MsgType const &type, const char* Function, + const char* Description,...) __like_printf(4) __cold; + /** \brief add an fatal error message to the list * * Most of the stuff we consider as "error" is also "fatal" for @@ -169,6 +178,13 @@ public: /*{{{*/ */ bool Debug(const char *Description,...) __like_printf(2) __cold; + /** \brief adds an error message with the given type + * + * \param type of the error message + * \param Description of the error + */ + bool Insert(MsgType const &type, const char* Description,...) __like_printf(3) __cold; + /** \brief is an error in the list? * * \return \b true if an error is included in the list, \b false otherwise diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index 70732e4d0..2a4e200a7 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -173,7 +173,9 @@ bool UnMet(CommandLine &CmdL) } else { - APT::VersionSet verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1); + APT::CacheSetHelper helper(true, GlobalError::NOTICE); + APT::VersionSet verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1, + APT::VersionSet::CANDIDATE, helper); for (APT::VersionSet::iterator V = verset.begin(); V != verset.end(); ++V) if (ShowUnMet(V, Important) == false) return false; @@ -187,7 +189,8 @@ bool UnMet(CommandLine &CmdL) bool DumpPackage(CommandLine &CmdL) { pkgCacheFile CacheFile; - APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1); + APT::CacheSetHelper helper(true, GlobalError::NOTICE); + APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper); for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) { @@ -566,7 +569,7 @@ public: return pkgCache::VerIterator(Cache, 0); } - CacheSetHelperDepends() : CacheSetHelper(false) {} + CacheSetHelperDepends() : CacheSetHelper(false, GlobalError::NOTICE) {} }; bool ShowDepends(CommandLine &CmdL, bool const RevDepends) { @@ -754,11 +757,12 @@ bool XVcg(CommandLine &CmdL) } // Load the list of packages from the command line into the show list + APT::CacheSetHelper helper(true, GlobalError::NOTICE); std::list mods; mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX)); mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX)); std::map pkgsets = - APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0); + APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper); for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin(); Pkg != pkgsets[0].end(); ++Pkg) @@ -968,11 +972,12 @@ bool Dotty(CommandLine &CmdL) } // Load the list of packages from the command line into the show list + APT::CacheSetHelper helper(true, GlobalError::NOTICE); std::list mods; mods.push_back(APT::PackageSet::Modifier(0, ",", APT::PackageSet::Modifier::POSTFIX)); mods.push_back(APT::PackageSet::Modifier(1, "^", APT::PackageSet::Modifier::POSTFIX)); std::map pkgsets = - APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0); + APT::PackageSet::GroupedFromCommandLine(CacheFile, CmdL.FileList + 1, mods, 0, helper); for (APT::PackageSet::const_iterator Pkg = pkgsets[0].begin(); Pkg != pkgsets[0].end(); ++Pkg) @@ -1403,9 +1408,10 @@ bool ShowAuto(CommandLine &CmdL) bool ShowPackage(CommandLine &CmdL) { pkgCacheFile CacheFile; + APT::CacheSetHelper helper(true, GlobalError::NOTICE); APT::VersionSet::Version const select = _config->FindB("APT::Cache::AllVersions", true) ? APT::VersionSet::ALL : APT::VersionSet::CANDIDATE; - APT::VersionSet const verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1, select); + APT::VersionSet const verset = APT::VersionSet::FromCommandLine(CacheFile, CmdL.FileList + 1, select, helper); for (APT::VersionSet::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver) if (DisplayRecord(CacheFile, Ver) == false) return false; @@ -1564,7 +1570,8 @@ bool Policy(CommandLine &CmdL) (InstalledLessCandidate > 0 ? (InstalledLessCandidate) : 0) - 1; // Print out detailed information for each package - APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1); + APT::CacheSetHelper helper(true, GlobalError::NOTICE); + APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper); for (APT::PackageSet::const_iterator I = pkgset.begin(); I != pkgset.end(); ++I) { pkgCache::PkgIterator Pkg = I.Group().FindPkg("any"); @@ -1644,7 +1651,8 @@ bool Madison(CommandLine &CmdL) if (_error->PendingError() == true) _error->Discard(); - APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1); + APT::CacheSetHelper helper(true, GlobalError::NOTICE); + APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper); for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) { if (Pkg.end() == false) diff --git a/debian/changelog b/debian/changelog index d6bfa76ee..bd3400d2b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,13 +1,17 @@ apt (0.7.26~exp12) UNRELEASEDexperimental; urgency=low + [ Michael Vogt ] * debian/control: - add dependency on zlib-dev for libapt-pkg-dev - * apt-pkg/cacheset.cc: - - make CacheSetHelper::canNotFindAllVer display a notice - only (for compat reasons). Otherwise tools like sbuild - blow up - -- Michael Vogt Thu, 29 Jul 2010 23:45:42 +0200 + [ David Kalnischkies ] + * apt-pkg/cacheset.cc: + - [ABI BREAK] add an ErrorType option to CacheSetHelper + * cmdline/apt-cache.cc: + - use Notice instead of Error in the CacheSetHelper messages + for compat reasons. Otherwise tools like sbuild blow up + + -- David Kalnischkies Fri, 30 Jul 2010 09:48:04 +0200 apt (0.7.26~exp11) experimental; urgency=low -- cgit v1.2.3-70-g09d2