diff options
Diffstat (limited to 'apt-pkg')
31 files changed, 587 insertions, 197 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index c48443eff..97b2d1e29 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -984,6 +984,8 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, DestFile += ".decomp"; Desc.URI = decompProg + ":" + FileName; QueueURI(Desc); + + // FIXME: this points to a c++ string that goes out of scope Mode = decompProg.c_str(); } /*}}}*/ @@ -1067,8 +1069,7 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, /*{{{*/ string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(RealURI); - struct stat Buf; - if (stat(Final.c_str(),&Buf) == 0) + if (RealFileExists(Final) == true) { // File was already in place. It needs to be re-downloaded/verified // because Release might have changed, we do give it a differnt @@ -1082,6 +1083,19 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, /*{{{*/ QueueURI(Desc); } /*}}}*/ +pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ +{ + // if the file was never queued undo file-changes done in the constructor + if (QueueCounter == 1 && Status == StatIdle && FileSize == 0 && Complete == false && + LastGoodSig.empty() == false) + { + string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); + if (RealFileExists(Final) == false && RealFileExists(LastGoodSig) == true) + Rename(LastGoodSig, Final); + } + +} + /*}}}*/ // pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- /* The only header we use is the last-modified header. */ @@ -1369,9 +1383,20 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/ { HashString ExpectedIndexHash; const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey); + bool compressedAvailable = false; if (Record == NULL) { - if (verify == true && (*Target)->IsOptional() == false) + if ((*Target)->IsOptional() == true) + { + std::vector<std::string> types = APT::Configuration::getCompressionTypes(); + for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t) + if (MetaIndexParser->Exists(string((*Target)->MetaKey).append(".").append(*t)) == true) + { + compressedAvailable = true; + break; + } + } + else if (verify == true) { Status = StatAuthError; strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str()); @@ -1400,7 +1425,7 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/ if ((*Target)->IsSubIndex() == true) new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description, (*Target)->ShortDesc, ExpectedIndexHash); - else if (transInRelease == false || MetaIndexParser->Exists((*Target)->MetaKey) == true) + else if (transInRelease == false || Record != NULL || compressedAvailable == true) { if (_config->FindB("Acquire::PDiffs",true) == true && transInRelease == true && MetaIndexParser->Exists(string((*Target)->MetaKey).append(".diff/Index")) == true) @@ -1584,14 +1609,25 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner, /*{{{*/ // keep the old InRelease around in case of transistent network errors string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); - struct stat Buf; - if (stat(Final.c_str(),&Buf) == 0) + if (RealFileExists(Final) == true) { string const LastGoodSig = DestFile + ".reverify"; Rename(Final,LastGoodSig); } } /*}}}*/ +pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ +{ + // if the file was never queued undo file-changes done in the constructor + if (QueueCounter == 1 && Status == StatIdle && FileSize == 0 && Complete == false) + { + string const Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); + string const LastGoodSig = DestFile + ".reverify"; + if (RealFileExists(Final) == false && RealFileExists(LastGoodSig) == true) + Rename(LastGoodSig, Final); + } +} + /*}}}*/ // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- // FIXME: this can go away once the InRelease file is used widely diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 51d539450..10c855e63 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -774,6 +774,7 @@ class pkgAcqMetaSig : public pkgAcquire::Item std::string MetaIndexURI, std::string MetaIndexURIDesc, std::string MetaIndexShortDesc, const std::vector<struct IndexTarget*>* IndexTargets, indexRecords* MetaIndexParser); + virtual ~pkgAcqMetaSig(); }; /*}}}*/ /** \brief An item that is responsible for downloading the meta-index {{{ @@ -904,6 +905,7 @@ public: std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc, const std::vector<struct IndexTarget*>* IndexTargets, indexRecords* MetaIndexParser); + virtual ~pkgAcqMetaClearSig(); }; /*}}}*/ /** \brief An item that is responsible for fetching a package file. {{{ diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 85799a11b..69d4acd83 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -459,6 +459,49 @@ bool pkgAllUpgrade(pkgDepCache &Cache) return Fix.ResolveByKeep(); } /*}}}*/ +// AllUpgradeNoDelete - Upgrade without removing packages /*{{{*/ +// --------------------------------------------------------------------- +/* Right now the system must be consistent before this can be called. + * Upgrade as much as possible without deleting anything (useful for + * stable systems) + */ +bool pkgAllUpgradeNoDelete(pkgDepCache &Cache) +{ + pkgDepCache::ActionGroup group(Cache); + + pkgProblemResolver Fix(&Cache); + + if (Cache.BrokenCount() != 0) + return false; + + // provide the initial set of stuff we want to upgrade by marking + // all upgradable packages for upgrade + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + { + if (I->CurrentVer != 0 && Cache[I].InstallVer != 0) + { + if (_config->FindB("APT::Ignore-Hold",false) == false) + if (I->SelectedState == pkgCache::State::Hold) + continue; + + Cache.MarkInstall(I, false, 0, false); + } + } + + // then let auto-install loose + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (Cache[I].Install()) + Cache.MarkInstall(I, true, 0, false); + + // ... but it may remove stuff, we we need to clean up afterwards again + for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I) + if (Cache[I].Delete() == true) + Cache.MarkKeep(I, false, false); + + // resolve remaining issues via keep + return Fix.ResolveByKeep(); +} + /*}}}*/ // MinimizeUpgrade - Minimizes the set of packages to be upgraded /*{{{*/ // --------------------------------------------------------------------- /* This simply goes over the entire set of packages and tries to keep @@ -550,14 +593,12 @@ void pkgProblemResolver::MakeScores() unsigned long Size = Cache.Head().PackageCount; memset(Scores,0,sizeof(*Scores)*Size); - // Maps to pkgCache::State::VerPriority - // which is "Important Required Standard Optional Extra" - // (yes, that is confusing, the order of pkgCache::State::VerPriority - // needs to be adjusted but that requires a ABI break) + // maps to pkgCache::State::VerPriority: + // Required Important Standard Optional Extra int PrioMap[] = { 0, - _config->FindI("pkgProblemResolver::Scores::Important",2), _config->FindI("pkgProblemResolver::Scores::Required",3), + _config->FindI("pkgProblemResolver::Scores::Important",2), _config->FindI("pkgProblemResolver::Scores::Standard",1), _config->FindI("pkgProblemResolver::Scores::Optional",-1), _config->FindI("pkgProblemResolver::Scores::Extra",-2) diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 7f58c8eed..a499db8ba 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -143,7 +143,11 @@ class pkgProblemResolver /*{{{*/ bool pkgDistUpgrade(pkgDepCache &Cache); bool pkgApplyStatus(pkgDepCache &Cache); bool pkgFixBroken(pkgDepCache &Cache); + bool pkgAllUpgrade(pkgDepCache &Cache); + +bool pkgAllUpgradeNoDelete(pkgDepCache &Cache); + bool pkgMinimizeUpgrade(pkgDepCache &Cache); void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List); diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 37c846582..4f9b84e00 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -388,12 +388,12 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache if (dpkgMultiArch == 0) { close(external[0]); std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory"); - if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0) - _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --print-foreign-architectures", chrootDir.c_str()); int const nullfd = open("/dev/null", O_RDONLY); dup2(nullfd, STDIN_FILENO); dup2(external[1], STDOUT_FILENO); dup2(nullfd, STDERR_FILENO); + if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0 && chdir("/") != 0) + _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --print-foreign-architectures", chrootDir.c_str()); execvp(Args[0], (char**) &Args[0]); _error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!"); _exit(100); diff --git a/apt-pkg/cachefilter.cc b/apt-pkg/cachefilter.cc index 64cde41d1..57b9af159 100644 --- a/apt-pkg/cachefilter.cc +++ b/apt-pkg/cachefilter.cc @@ -55,6 +55,17 @@ PackageNameMatchesRegEx::~PackageNameMatchesRegEx() { /*{{{*/ } /*}}}*/ +// Fnmatch support /*{{{*/ +//---------------------------------------------------------------------- +bool PackageNameMatchesFnmatch::operator() (pkgCache::PkgIterator const &Pkg) {/*{{{*/ + return fnmatch(Pattern.c_str(), Pkg.Name(), FNM_CASEFOLD) == 0; +} + /*}}}*/ +bool PackageNameMatchesFnmatch::operator() (pkgCache::GrpIterator const &Grp) {/*{{{*/ + return fnmatch(Pattern.c_str(), Grp.Name(), FNM_CASEFOLD) == 0; +} + /*}}}*/ + // CompleteArch to <kernel>-<cpu> tuple /*{{{*/ //---------------------------------------------------------------------- /* The complete architecture, consisting of <kernel>-<cpu>. */ diff --git a/apt-pkg/cachefilter.h b/apt-pkg/cachefilter.h index 25cd43f47..34b7d0b46 100644 --- a/apt-pkg/cachefilter.h +++ b/apt-pkg/cachefilter.h @@ -14,6 +14,10 @@ /*}}}*/ namespace APT { namespace CacheFilter { + +#define PACKAGE_MATCHER_ABI_COMPAT 1 +#ifdef PACKAGE_MATCHER_ABI_COMPAT + // PackageNameMatchesRegEx /*{{{*/ class PackageNameMatchesRegEx { /** \brief dpointer placeholder (for later in case we need it) */ @@ -26,6 +30,19 @@ public: ~PackageNameMatchesRegEx(); }; /*}}}*/ +// PackageNameMatchesFnmatch /*{{{*/ + class PackageNameMatchesFnmatch { + /** \brief dpointer placeholder (for later in case we need it) */ + void *d; + const std::string Pattern; +public: + PackageNameMatchesFnmatch(std::string const &Pattern) + : Pattern(Pattern) {}; + bool operator() (pkgCache::PkgIterator const &Pkg); + bool operator() (pkgCache::GrpIterator const &Grp); + ~PackageNameMatchesFnmatch() {}; +}; + /*}}}*/ // PackageArchitectureMatchesSpecification /*{{{*/ /** \class PackageArchitectureMatchesSpecification \brief matching against architecture specification strings @@ -55,6 +72,73 @@ public: bool operator() (pkgCache::VerIterator const &Ver); ~PackageArchitectureMatchesSpecification(); }; + +#else + +class PackageMatcher { + public: + virtual bool operator() (pkgCache::PkgIterator const &Pkg) { return false; }; + virtual bool operator() (pkgCache::GrpIterator const &Grp) { return false; }; + virtual bool operator() (pkgCache::VerIterator const &Ver) { return false; }; + + virtual ~PackageMatcher() {}; +}; + +// PackageNameMatchesRegEx /*{{{*/ +class PackageNameMatchesRegEx : public PackageMatcher { + /** \brief dpointer placeholder (for later in case we need it) */ + void *d; + regex_t* pattern; +public: + PackageNameMatchesRegEx(std::string const &Pattern); + virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::GrpIterator const &Grp); + virtual ~PackageNameMatchesRegEx(); +}; + /*}}}*/ +// PackageNameMatchesFnmatch /*{{{*/ + class PackageNameMatchesFnmatch : public PackageMatcher{ + /** \brief dpointer placeholder (for later in case we need it) */ + void *d; + const std::string Pattern; +public: + PackageNameMatchesFnmatch(std::string const &Pattern) + : Pattern(Pattern) {}; + virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::GrpIterator const &Grp); + virtual ~PackageNameMatchesFnmatch() {}; +}; + /*}}}*/ +// PackageArchitectureMatchesSpecification /*{{{*/ +/** \class PackageArchitectureMatchesSpecification + \brief matching against architecture specification strings + + The strings are of the format <kernel>-<cpu> where either component, + or the whole string, can be the wildcard "any" as defined in + debian-policy §11.1 "Architecture specification strings". + + Examples: i386, mipsel, linux-any, any-amd64, any */ +class PackageArchitectureMatchesSpecification : public PackageMatcher { + std::string literal; + std::string complete; + bool isPattern; + /** \brief dpointer placeholder (for later in case we need it) */ + void *d; +public: + /** \brief matching against architecture specification strings + * + * @param pattern is the architecture specification string + * @param isPattern defines if the given \b pattern is a + * architecture specification pattern to match others against + * or if it is the fixed string and matched against patterns + */ + PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern = true); + bool operator() (char const * const &arch); + virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::VerIterator const &Ver); + virtual ~PackageArchitectureMatchesSpecification(); +}; +#endif /*}}}*/ } } diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 1fea4f94a..0147f7e86 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -155,6 +155,69 @@ bool PackageContainerInterface::FromRegEx(PackageContainerInterface * const pci, return true; } /*}}}*/ +// FromFnmatch - Returns the package defined by this fnmatch /*{{{*/ +bool +PackageContainerInterface::FromFnmatch(PackageContainerInterface * const pci, + pkgCacheFile &Cache, + std::string pattern, + CacheSetHelper &helper) +{ + static const char * const isfnmatch = ".?*[]!"; + if (pattern.find_first_of(isfnmatch) == std::string::npos) + return false; + + bool const wasEmpty = pci->empty(); + if (wasEmpty == true) + pci->setConstructor(FNMATCH); + + size_t archfound = pattern.find_last_of(':'); + std::string arch = "native"; + if (archfound != std::string::npos) { + arch = pattern.substr(archfound+1); + if (arch.find_first_of(isfnmatch) == std::string::npos) + pattern.erase(archfound); + else + arch = "native"; + } + + if (unlikely(Cache.GetPkgCache() == 0)) + return false; + + APT::CacheFilter::PackageNameMatchesFnmatch filter(pattern); + + bool found = false; + for (pkgCache::GrpIterator Grp = Cache.GetPkgCache()->GrpBegin(); Grp.end() == false; ++Grp) { + if (filter(Grp) == false) + continue; + pkgCache::PkgIterator Pkg = Grp.FindPkg(arch); + if (Pkg.end() == true) { + if (archfound == std::string::npos) { + std::vector<std::string> archs = APT::Configuration::getArchitectures(); + for (std::vector<std::string>::const_iterator a = archs.begin(); + a != archs.end() && Pkg.end() != true; ++a) + Pkg = Grp.FindPkg(*a); + } + if (Pkg.end() == true) + continue; + } + + pci->insert(Pkg); + helper.showRegExSelection(Pkg, pattern); + found = true; + } + + if (found == false) { + helper.canNotFindRegEx(pci, Cache, pattern); + pci->setConstructor(UNKNOWN); + return false; + } + + if (wasEmpty == false && pci->getConstructor() != UNKNOWN) + pci->setConstructor(UNKNOWN); + + return true; +} + /*}}}*/ // FromName - Returns the package defined by this string /*{{{*/ pkgCache::PkgIterator PackageContainerInterface::FromName(pkgCacheFile &Cache, std::string const &str, CacheSetHelper &helper) { @@ -239,6 +302,7 @@ bool PackageContainerInterface::FromString(PackageContainerInterface * const pci if (FromGroup(pci, Cache, str, helper) == false && FromTask(pci, Cache, str, helper) == false && + FromFnmatch(pci, Cache, str, helper) == false && FromRegEx(pci, Cache, str, helper) == false) { helper.canNotFindPackage(pci, Cache, str); diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 2a45910ba..29103aad9 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -11,7 +11,6 @@ // Include Files /*{{{*/ #include <iostream> #include <fstream> -#include <list> #include <map> #include <set> #include <list> @@ -132,13 +131,14 @@ public: virtual bool empty() const = 0; virtual void clear() = 0; - enum Constructor { UNKNOWN, REGEX, TASK }; + enum Constructor { UNKNOWN, REGEX, TASK, FNMATCH }; virtual void setConstructor(Constructor const &con) = 0; virtual Constructor getConstructor() const = 0; static bool FromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static bool FromRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static pkgCache::PkgIterator FromName(pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper); + static bool FromFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static bool FromGroup(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper); static bool FromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern, CacheSetHelper &helper); static bool FromCommandLine(PackageContainerInterface * const pci, pkgCacheFile &Cache, const char **cmdline, CacheSetHelper &helper); @@ -260,6 +260,16 @@ public: /*{{{*/ return FromRegEx(Cache, pattern, helper); } + static PackageContainer FromFnmatch(pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) { + PackageContainer cont(FNMATCH); + PackageContainerInterface::FromFnmatch(&cont, Cache, pattern, helper); + return cont; + } + static PackageContainer FromFnMatch(pkgCacheFile &Cache, std::string const &pattern) { + CacheSetHelper helper; + return FromFnmatch(Cache, pattern, helper); + } + /** \brief returns a package specified by a string \param Cache the package is in diff --git a/apt-pkg/cdrom.h b/apt-pkg/cdrom.h index 4fc3d3928..7d19eb813 100644 --- a/apt-pkg/cdrom.h +++ b/apt-pkg/cdrom.h @@ -18,7 +18,7 @@ class pkgCdromStatus /*{{{*/ int totalSteps; public: - pkgCdromStatus() {}; + pkgCdromStatus() : totalSteps(0) {}; virtual ~pkgCdromStatus() {}; // total steps diff --git a/apt-pkg/contrib/cdromutl.cc b/apt-pkg/contrib/cdromutl.cc index 187f6bd59..afa01a562 100644 --- a/apt-pkg/contrib/cdromutl.cc +++ b/apt-pkg/contrib/cdromutl.cc @@ -122,8 +122,9 @@ bool MountCdrom(string Path, string DeviceName) if (Child == 0) { // Make all the fds /dev/null + int null_fd = open("/dev/null",O_RDWR); for (int I = 0; I != 3; I++) - dup2(open("/dev/null",O_RDWR),I); + dup2(null_fd, I); if (_config->Exists("Acquire::cdrom::"+Path+"::Mount") == true) { diff --git a/apt-pkg/contrib/cmndline.cc b/apt-pkg/contrib/cmndline.cc index 75d02cad4..2086d91ca 100644 --- a/apt-pkg/contrib/cmndline.cc +++ b/apt-pkg/contrib/cmndline.cc @@ -38,6 +38,42 @@ CommandLine::~CommandLine() delete [] FileList; } /*}}}*/ +// CommandLine::GetCommand - return the first non-option word /*{{{*/ +char const * CommandLine::GetCommand(Dispatch const * const Map, + unsigned int const argc, char const * const * const argv) +{ + // if there is a -- on the line there must be the word we search for around it + // as -- marks the end of the options, just not sure if the command can be + // considered an option or not, so accept both + for (size_t i = 1; i < argc; ++i) + { + if (strcmp(argv[i], "--") != 0) + continue; + ++i; + if (i < argc) + for (size_t j = 0; Map[j].Match != NULL; ++j) + if (strcmp(argv[i], Map[j].Match) == 0) + return Map[j].Match; + i -= 2; + if (i != 0) + for (size_t j = 0; Map[j].Match != NULL; ++j) + if (strcmp(argv[i], Map[j].Match) == 0) + return Map[j].Match; + return NULL; + } + // no --, so search for the first word matching a command + // FIXME: How like is it that an option parameter will be also a valid Match ? + for (size_t i = 1; i < argc; ++i) + { + if (*(argv[i]) == '-') + continue; + for (size_t j = 0; Map[j].Match != NULL; ++j) + if (strcmp(argv[i], Map[j].Match) == 0) + return Map[j].Match; + } + return NULL; +} + /*}}}*/ // CommandLine::Parse - Main action member /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -361,6 +397,7 @@ bool CommandLine::DispatchArg(Dispatch *Map,bool NoMatch) void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * const argv) { char cmdline[100 + argc * 50]; + memset(cmdline, 0, sizeof(cmdline)); unsigned int length = 0; bool lastWasOption = false; bool closeQuote = false; @@ -390,3 +427,15 @@ void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * co _config->Set("CommandLine::AsString", cmdline); } /*}}}*/ +CommandLine::Args CommandLine::MakeArgs(char ShortOpt, char const *LongOpt, char const *ConfName, unsigned long Flags)/*{{{*/ +{ + /* In theory, this should be a constructor for CommandLine::Args instead, + but this breaks compatibility as gcc thinks this is a c++11 initializer_list */ + CommandLine::Args arg; + arg.ShortOpt = ShortOpt; + arg.LongOpt = LongOpt; + arg.ConfName = ConfName; + arg.Flags = Flags; + return arg; +} + /*}}}*/ diff --git a/apt-pkg/contrib/cmndline.h b/apt-pkg/contrib/cmndline.h index 9f505fd41..180276633 100644 --- a/apt-pkg/contrib/cmndline.h +++ b/apt-pkg/contrib/cmndline.h @@ -83,6 +83,12 @@ class CommandLine unsigned int FileSize() const; bool DispatchArg(Dispatch *List,bool NoMatch = true); + static char const * GetCommand(Dispatch const * const Map, + unsigned int const argc, char const * const * const argv); + + static CommandLine::Args MakeArgs(char ShortOpt, char const *LongOpt, + char const *ConfName, unsigned long Flags); + CommandLine(Args *AList,Configuration *Conf); ~CommandLine(); }; diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 808a708a1..4ef4663c0 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -422,6 +422,18 @@ void Configuration::Clear(string const &Name, string const &Value) } /*}}}*/ +// Configuration::Clear - Clear everything /*{{{*/ +// --------------------------------------------------------------------- +void Configuration::Clear() +{ + const Configuration::Item *Top = Tree(0); + while( Top != 0 ) + { + Clear(Top->FullTag()); + Top = Top->Next; + } +} + /*}}}*/ // Configuration::Clear - Clear an entire tree /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -811,7 +823,7 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio // Go down a level if (TermChar == '{') { - if (StackPos <= 100) + if (StackPos < sizeof(Stack)/sizeof(std::string)) Stack[StackPos++] = ParentTag; /* Make sectional tags incorperate the section into the diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index ea94c2fe6..8e09ea0a6 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -94,6 +94,7 @@ class Configuration // clear a whole tree void Clear(const std::string &Name); + void Clear(); // remove a certain value from a list (e.g. the list of "APT::Keep-Fds") void Clear(std::string const &List, std::string const &Value); diff --git a/apt-pkg/contrib/error.cc b/apt-pkg/contrib/error.cc index 122e2c809..d457781c3 100644 --- a/apt-pkg/contrib/error.cc +++ b/apt-pkg/contrib/error.cc @@ -67,9 +67,10 @@ bool GlobalError::NAME (const char *Function, const char *Description,...) { \ int const errsv = errno; \ while (true) { \ va_start(args,Description); \ - if (InsertErrno(TYPE, Function, Description, args, errsv, msgSize) == false) \ - break; \ + bool const retry = InsertErrno(TYPE, Function, Description, args, errsv, msgSize); \ va_end(args); \ + if (retry == false) \ + break; \ } \ return false; \ } @@ -88,9 +89,10 @@ bool GlobalError::InsertErrno(MsgType const &type, const char *Function, int const errsv = errno; while (true) { va_start(args,Description); - if (InsertErrno(type, Function, Description, args, errsv, msgSize) == false) - break; + bool const retry = InsertErrno(type, Function, Description, args, errsv, msgSize); va_end(args); + if (retry == false) + break; } return false; } diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 0f88923cf..4806ae3f9 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -41,6 +41,8 @@ #include <dirent.h> #include <signal.h> #include <errno.h> +#include <glob.h> + #include <set> #include <algorithm> @@ -244,17 +246,20 @@ int GetLock(string File,bool Errors) fl.l_len = 0; if (fcntl(FD,F_SETLK,&fl) == -1) { + // always close to not leak resources + int Tmp = errno; + close(FD); + errno = Tmp; + if (errno == ENOLCK) { _error->Warning(_("Not using locking for nfs mounted lock file %s"),File.c_str()); return dup(0); // Need something for the caller to close - } + } + if (Errors == true) _error->Errno("open",_("Could not get lock %s"),File.c_str()); - int Tmp = errno; - close(FD); - errno = Tmp; return -1; } @@ -941,9 +946,6 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co if ((Mode & Atomic) == Atomic) { Flags |= Replace; - char *name = strdup((FileName + ".XXXXXX").c_str()); - TemporaryFileName = string(mktemp(name)); - free(name); } else if ((Mode & (Exclusive | Create)) == (Exclusive | Create)) { @@ -966,11 +968,24 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co if_FLAGGED_SET(Create, O_CREAT); if_FLAGGED_SET(Empty, O_TRUNC); if_FLAGGED_SET(Exclusive, O_EXCL); - else if_FLAGGED_SET(Atomic, O_EXCL); #undef if_FLAGGED_SET - if (TemporaryFileName.empty() == false) - iFd = open(TemporaryFileName.c_str(), fileflags, Perms); + if ((Mode & Atomic) == Atomic) + { + char *name = strdup((FileName + ".XXXXXX").c_str()); + + if((iFd = mkstemp(name)) == -1) + { + free(name); + return FileFdErrno("mkostemp", "Could not create temporary file for %s", FileName.c_str()); + } + + TemporaryFileName = string(name); + free(name); + + if(Perms != 600 && fchmod(iFd, Perms) == -1) + return FileFdErrno("fchmod", "Could not change permissions for temporary file %s", TemporaryFileName.c_str()); + } else iFd = open(FileName.c_str(), fileflags, Perms); @@ -1218,11 +1233,9 @@ FileFd::~FileFd() { Close(); if (d != NULL) - { d->CloseDown(FileName); - delete d; - d = NULL; - } + delete d; + d = NULL; } /*}}}*/ // FileFd::Read - Read a bit of the file /*{{{*/ @@ -1598,7 +1611,11 @@ unsigned long long FileFd::Size() char ignore[1000]; unsigned long long read = 0; do { - Read(ignore, sizeof(ignore), &read); + if (Read(ignore, sizeof(ignore), &read) == false) + { + Seek(oldSeek); + return 0; + } } while(read != 0); size = Tell(); Seek(oldSeek); @@ -1615,10 +1632,16 @@ unsigned long long FileFd::Size() * bits of the file */ // FIXME: Size for gz-files is limited by 32bit… no largefile support if (lseek(iFd, -4, SEEK_END) < 0) - return FileFdErrno("lseek","Unable to seek to end of gzipped file"); - size = 0L; + { + FileFdErrno("lseek","Unable to seek to end of gzipped file"); + return 0; + } + size = 0; if (read(iFd, &size, 4) != 4) - return FileFdErrno("read","Unable to read original size of gzipped file"); + { + FileFdErrno("read","Unable to read original size of gzipped file"); + return 0; + } #ifdef WORDS_BIGENDIAN uint32_t tmp_size = size; @@ -1628,7 +1651,10 @@ unsigned long long FileFd::Size() #endif if (lseek(iFd, oldPos, SEEK_SET) < 0) - return FileFdErrno("lseek","Unable to seek in gzipped file"); + { + FileFdErrno("lseek","Unable to seek in gzipped file"); + return 0; + } return size; } @@ -1752,3 +1778,33 @@ bool FileFd::FileFdError(const char *Description,...) { /*}}}*/ gzFile FileFd::gzFd() { return (gzFile) d->gz; } + + +// Glob - wrapper around "glob()" /*{{{*/ +// --------------------------------------------------------------------- +/* */ +std::vector<std::string> Glob(std::string const &pattern, int flags) +{ + std::vector<std::string> result; + glob_t globbuf; + int glob_res; + unsigned int i; + + glob_res = glob(pattern.c_str(), flags, NULL, &globbuf); + + if (glob_res != 0) + { + if(glob_res != GLOB_NOMATCH) { + _error->Errno("glob", "Problem with glob"); + return result; + } + } + + // append results + for(i=0;i<globbuf.gl_pathc;i++) + result.push_back(string(globbuf.gl_pathv[i])); + + globfree(&globbuf); + return result; +} + /*}}}*/ diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 3ec01dd9a..decd64d9d 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -191,4 +191,7 @@ std::string flNoLink(std::string File); std::string flExtension(std::string File); std::string flCombine(std::string Dir,std::string File); +// simple c++ glob +std::vector<std::string> Glob(std::string const &pattern, int flags=0); + #endif diff --git a/apt-pkg/contrib/sha2.h b/apt-pkg/contrib/sha2.h index 51c921dbd..8e0c99a1b 100644 --- a/apt-pkg/contrib/sha2.h +++ b/apt-pkg/contrib/sha2.h @@ -60,10 +60,11 @@ class SHA256Summation : public SHA2SummationBase res.Set(Sum); return res; }; - SHA256Summation() + SHA256Summation() { SHA256_Init(&ctx); Done = false; + memset(&Sum, 0, sizeof(Sum)); }; }; @@ -96,6 +97,7 @@ class SHA512Summation : public SHA2SummationBase { SHA512_Init(&ctx); Done = false; + memset(&Sum, 0, sizeof(Sum)); }; }; diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index d0e74d8c5..0955b69f7 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -943,6 +943,8 @@ bool StrToTime(const string &Val,time_t &Result) Tm.tm_isdst = 0; if (Month[0] != 0) Tm.tm_mon = MonthConv(Month); + else + Tm.tm_mon = 0; // we don't have a month, so pick something Tm.tm_year -= 1900; // Convert to local time and then to GMT @@ -1233,12 +1235,12 @@ char *safe_snprintf(char *Buffer,char *End,const char *Format,...) va_list args; int Did; - va_start(args,Format); - if (End <= Buffer) return End; - + va_start(args,Format); Did = vsnprintf(Buffer,End - Buffer,Format,args); + va_end(args); + if (Did < 0 || Buffer + Did > End) return End; return Buffer + Did; @@ -1291,6 +1293,18 @@ bool CheckDomainList(const string &Host,const string &List) return false; } /*}}}*/ +// strv_length - Return the length of a NULL-terminated string array /*{{{*/ +// --------------------------------------------------------------------- +/* */ +size_t strv_length(const char **str_array) +{ + size_t i; + for (i=0; str_array[i] != NULL; i++) + /* nothing */ + ; + return i; +} + // DeEscapeString - unescape (\0XX and \xXX) from a string /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index e92f91dc0..530896141 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -108,6 +108,10 @@ inline int stringcasecmp(std::string::const_iterator A,std::string::const_iterat APT_MKSTRCMP2(stringcmp,stringcmp); APT_MKSTRCMP2(stringcasecmp,stringcasecmp); +// Return the length of a NULL-terminated string array +size_t strv_length(const char **str_array); + + inline const char *DeNull(const char *s) {return (s == 0?"(null)":s);}; class URI diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 28857176b..87aab6ee2 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -805,94 +805,28 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI, map_ptrloc const storage = WriteUniqString(component); FileI->Component = storage; - // FIXME: should use FileFd and TagSection - FILE* release = fdopen(dup(File.Fd()), "r"); - if (release == NULL) + pkgTagFile TagFile(&File, File.Size()); + pkgTagSection Section; + if (_error->PendingError() == true || TagFile.Step(Section) == false) return false; - char buffer[101]; - while (fgets(buffer, sizeof(buffer), release) != NULL) - { - size_t len = 0; - - // Skip empty lines - for (; buffer[len] == '\r' && buffer[len] == '\n'; ++len) - /* nothing */ - ; - if (buffer[len] == '\0') - continue; - - // seperate the tag from the data - const char* dataStart = strchr(buffer + len, ':'); - if (dataStart == NULL) - continue; - len = dataStart - buffer; - for (++dataStart; *dataStart == ' '; ++dataStart) - /* nothing */ - ; - const char* dataEnd = (const char*)rawmemchr(dataStart, '\0'); - // The last char should be a newline, but we can never be sure: #633350 - const char* lineEnd = dataEnd; - for (--lineEnd; *lineEnd == '\r' || *lineEnd == '\n'; --lineEnd) - /* nothing */ - ; - ++lineEnd; - - // which datastorage need to be updated - enum { Suite, Component, Version, Origin, Codename, Label, None } writeTo = None; - if (buffer[0] == ' ') - ; - #define APT_PARSER_WRITETO(X) else if (strncmp(#X, buffer, len) == 0) writeTo = X; - APT_PARSER_WRITETO(Suite) - APT_PARSER_WRITETO(Component) - APT_PARSER_WRITETO(Version) - APT_PARSER_WRITETO(Origin) - APT_PARSER_WRITETO(Codename) - APT_PARSER_WRITETO(Label) - #undef APT_PARSER_WRITETO - #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \ - pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, lineEnd); - APT_PARSER_FLAGIT(NotAutomatic) - APT_PARSER_FLAGIT(ButAutomaticUpgrades) - #undef APT_PARSER_FLAGIT - - // load all data from the line and save it - string data; - if (writeTo != None) - data.append(dataStart, dataEnd); - if (sizeof(buffer) - 1 == (dataEnd - buffer)) - { - while (fgets(buffer, sizeof(buffer), release) != NULL) - { - if (writeTo != None) - data.append(buffer); - if (strlen(buffer) != sizeof(buffer) - 1) - break; - } - } - if (writeTo != None) - { - // remove spaces and stuff from the end of the data line - for (std::string::reverse_iterator s = data.rbegin(); - s != data.rend(); ++s) - { - if (*s != '\r' && *s != '\n' && *s != ' ') - break; - *s = '\0'; - } - map_ptrloc const storage = WriteUniqString(data); - switch (writeTo) { - case Suite: FileI->Archive = storage; break; - case Component: FileI->Component = storage; break; - case Version: FileI->Version = storage; break; - case Origin: FileI->Origin = storage; break; - case Codename: FileI->Codename = storage; break; - case Label: FileI->Label = storage; break; - case None: break; - } - } + std::string data; + #define APT_INRELEASE(TAG, STORE) \ + data = Section.FindS(TAG); \ + if (data.empty() == false) \ + { \ + map_ptrloc const storage = WriteUniqString(data); \ + STORE = storage; \ } - fclose(release); + APT_INRELEASE("Suite", FileI->Archive) + APT_INRELEASE("Component", FileI->Component) + APT_INRELEASE("Version", FileI->Version) + APT_INRELEASE("Origin", FileI->Origin) + APT_INRELEASE("Codename", FileI->Codename) + APT_INRELEASE("Label", FileI->Label) + #undef APT_INRELEASE + Section.FindFlag("NotAutomatic", FileI->Flags, pkgCache::Flag::NotAutomatic); + Section.FindFlag("ButAutomaticUpgrades", FileI->Flags, pkgCache::Flag::ButAutomaticUpgrades); return !_error->PendingError(); } diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 7dd5ab2bf..b597b6f3c 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -238,6 +238,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description, (*Target)->ShortDesc, HashString()); } + delete targets; // this is normally created in pkgAcqMetaSig, but if we run // in --print-uris mode, we add it here diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 3fb80d158..3c1013761 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -134,6 +134,8 @@ static void dpkgChrootDirectory() std::cerr << "Chrooting into " << chrootDir << std::endl; if (chroot(chrootDir.c_str()) != 0) _exit(100); + if (chdir("/") != 0) + _exit(100); } /*}}}*/ @@ -294,7 +296,7 @@ bool pkgDPkgPM::SendPkgsInfo(FILE * const F, unsigned int const &Version) if (CurVer.end() == true && (I->Op == Item::Remove || I->Op == Item::Purge)) CurVer = FindNowVersion(I->Pkg); - else if (CurVer.end() == true) + if (CurVer.end() == true) { if (Version <= 2) fprintf(F, "- "); @@ -380,24 +382,32 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) OptSec = "DPkg::Tools::Options::" + string(Opts->Value.c_str(),Pos); unsigned int Version = _config->FindI(OptSec+"::Version",1); + unsigned int InfoFD = _config->FindI(OptSec + "::InfoFD", STDIN_FILENO); // Create the pipes int Pipes[2]; if (pipe(Pipes) != 0) return _error->Errno("pipe","Failed to create IPC pipe to subprocess"); - SetCloseExec(Pipes[0],true); + if (InfoFD != (unsigned)Pipes[0]) + SetCloseExec(Pipes[0],true); + else + _config->Set("APT::Keep-Fds::", Pipes[0]); SetCloseExec(Pipes[1],true); - + // Purified Fork for running the script - pid_t Process = ExecFork(); + pid_t Process = ExecFork(); if (Process == 0) { // Setup the FDs - dup2(Pipes[0],STDIN_FILENO); + dup2(Pipes[0], InfoFD); SetCloseExec(STDOUT_FILENO,false); - SetCloseExec(STDIN_FILENO,false); + SetCloseExec(STDIN_FILENO,false); SetCloseExec(STDERR_FILENO,false); + string hookfd; + strprintf(hookfd, "%d", InfoFD); + setenv("APT_HOOK_INFO_FD", hookfd.c_str(), 1); + dpkgChrootDirectory(); const char *Args[4]; Args[0] = "/bin/sh"; @@ -407,6 +417,8 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) execv(Args[0],(char **)Args); _exit(100); } + if (InfoFD == (unsigned)Pipes[0]) + _config->Clear("APT::Keep-Fds", Pipes[0]); close(Pipes[0]); FILE *F = fdopen(Pipes[1],"w"); if (F == 0) @@ -752,13 +764,15 @@ bool pkgDPkgPM::OpenLog() return _error->WarningE("OpenLog", _("Could not open file '%s'"), logfile_name.c_str()); setvbuf(d->term_out, NULL, _IONBF, 0); SetCloseExec(fileno(d->term_out), true); - struct passwd *pw; - struct group *gr; - pw = getpwnam("root"); - gr = getgrnam("adm"); - if (pw != NULL && gr != NULL) - chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid); - chmod(logfile_name.c_str(), 0640); + if (getuid() == 0) // if we aren't root, we can't chown a file, so don't try it + { + struct passwd *pw = getpwnam("root"); + struct group *gr = getgrnam("adm"); + if (pw != NULL && gr != NULL && chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid) != 0) + _error->WarningE("OpenLog", "chown to root:adm of file %s failed", logfile_name.c_str()); + } + if (chmod(logfile_name.c_str(), 0640) != 0) + _error->WarningE("OpenLog", "chmod 0640 of file %s failed", logfile_name.c_str()); fprintf(d->term_out, "\nLog started: %s\n", timestr); } @@ -1249,16 +1263,13 @@ bool pkgDPkgPM::Go(int OutStatusFd) // if tcgetattr does not return zero there was a error // and we do not do any pty magic - if (tcgetattr(0, &tt) == 0) + _error->PushToStack(); + if (tcgetattr(STDOUT_FILENO, &tt) == 0) { ioctl(0, TIOCGWINSZ, (char *)&win); - if (openpty(&master, &slave, NULL, &tt, &win) < 0) + if (openpty(&master, &slave, NULL, &tt, &win) < 0) { - const char *s = _("Can not write log, openpty() " - "failed (/dev/pts not mounted?)\n"); - fprintf(stderr, "%s",s); - if(d->term_out) - fprintf(d->term_out, "%s",s); + _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?")); master = slave = -1; } else { struct termios rtt; @@ -1276,6 +1287,15 @@ bool pkgDPkgPM::Go(int OutStatusFd) sigprocmask(SIG_SETMASK, &original_sigmask, 0); } } + // complain only if stdout is either a terminal (but still failed) or is an invalid + // descriptor otherwise we would complain about redirection to e.g. /dev/null as well. + else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF) + _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?")); + + if (_error->PendingError() == true) + _error->DumpErrors(std::cerr); + _error->RevertToStack(); + // Fork dpkg pid_t Child; _config->Set("APT::Keep-Fds::",fd[1]); diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 2c6eb43bf..978a893f7 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1007,9 +1007,6 @@ struct CompareProviders { else if ((B->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) return true; } - // higher priority seems like a good idea - if (AV->Priority != BV->Priority) - return AV->Priority > BV->Priority; // prefer native architecture if (strcmp(A.Arch(), B.Arch()) != 0) { @@ -1024,6 +1021,9 @@ struct CompareProviders { else if (*a == B.Arch()) return true; } + // higher priority seems like a good idea + if (AV->Priority != BV->Priority) + return AV->Priority > BV->Priority; // unable to decide… return A->ID < B->ID; } diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 1d61b974d..7694cb1dd 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -106,9 +106,9 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List, } else { Target.Open(TargetF,FileFd::WriteAtomic); } - FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); if (_error->PendingError() == true) return false; + FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); if (TargetFl == 0) return _error->Errno("fdopen","Failed to reopen fd"); @@ -601,6 +601,7 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList, (useInRelease ? inrelease.c_str() : releasegpg.c_str())); // something went wrong, don't copy the Release.gpg // FIXME: delete any existing gpg file? + delete MetaIndex; continue; } @@ -714,9 +715,9 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ } else { Target.Open(TargetF,FileFd::WriteAtomic); } - FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); if (_error->PendingError() == true) return false; + FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); if (TargetFl == 0) return _error->Errno("fdopen","Failed to reopen fd"); diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index e37a78cfb..8a72ca151 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -62,7 +62,7 @@ bool indexRecords::Load(const string Filename) /*{{{*/ if (OpenMaybeClearSignedFile(Filename, Fd) == false) return false; - pkgTagFile TagFile(&Fd, Fd.Size() + 256); // XXX + pkgTagFile TagFile(&Fd, Fd.Size()); if (_error->PendingError() == true) { strprintf(ErrorText, _("Unable to parse Release file %s"),Filename.c_str()); @@ -71,16 +71,11 @@ bool indexRecords::Load(const string Filename) /*{{{*/ pkgTagSection Section; const char *Start, *End; - // Skip over sections beginning with ----- as this is an idicator for clearsigns - do { - if (TagFile.Step(Section) == false) - { - strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str()); - return false; - } - - Section.Get (Start, End, 0); - } while (End - Start > 5 && strncmp(Start, "-----", 5) == 0); + if (TagFile.Step(Section) == false) + { + strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str()); + return false; + } Suite = Section.FindS("Suite"); Dist = Section.FindS("Codename"); diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 4ae3b5f87..0a06cc6e3 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -166,11 +166,15 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk tracks the default when the default is taken away, and a permanent pin that stays at that setting. */ + bool PrefSeen = false; for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) { /* Lets see if this version is the installed version */ bool instVer = (Pkg.CurrentVer() == Ver); + if (Pref == Ver) + PrefSeen = true; + for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF) { /* If this is the status file, and the current version is not the @@ -187,26 +191,33 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk { Pref = Ver; Max = Prio; + PrefSeen = true; } if (Prio > MaxAlt) { PrefAlt = Ver; MaxAlt = Prio; - } - } - + } + } + if (instVer == true && Max < 1000) { + /* Not having seen the Pref yet means we have a specific pin below 1000 + on a version below the current installed one, so ignore the specific pin + as this would be a downgrade otherwise */ + if (PrefSeen == false || Pref.end() == true) + { + Pref = Ver; + PrefSeen = true; + } /* Elevate our current selection (or the status file itself) to the Pseudo-status priority. */ - if (Pref.end() == true) - Pref = Ver; Max = 1000; - + // Fast path optimize. if (StatusOverride == false) break; - } + } } // If we do not find our candidate, use the one with the highest pin. // This means that if there is a version available with pin > 0; there diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 1c79ee74f..b91e868e2 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -50,21 +50,27 @@ public: /* */ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long long Size) { + /* The size is increased by 4 because if we start with the Size of the + filename we need to try to read 1 char more to see an EOF faster, 1 + char the end-pointer can be on and maybe 2 newlines need to be added + to the end of the file -> 4 extra chars */ + Size += 4; d = new pkgTagFilePrivate(pFd, Size); if (d->Fd.IsOpen() == false) - { d->Start = d->End = d->Buffer = 0; + else + d->Buffer = (char*)malloc(sizeof(char) * Size); + + if (d->Buffer == NULL) d->Done = true; - d->iOffset = 0; - return; - } - - d->Buffer = new char[Size]; + else + d->Done = false; + d->Start = d->End = d->Buffer; - d->Done = false; d->iOffset = 0; - Fill(); + if (d->Done == false) + Fill(); } /*}}}*/ // TagFile::~pkgTagFile - Destructor /*{{{*/ @@ -72,11 +78,11 @@ pkgTagFile::pkgTagFile(FileFd *pFd,unsigned long long Size) /* */ pkgTagFile::~pkgTagFile() { - delete [] d->Buffer; + free(d->Buffer); delete d; } /*}}}*/ -// TagFile::Offset - Return the current offset in the buffer /*{{{*/ +// TagFile::Offset - Return the current offset in the buffer /*{{{*/ unsigned long pkgTagFile::Offset() { return d->iOffset; @@ -89,19 +95,22 @@ unsigned long pkgTagFile::Offset() */ bool pkgTagFile::Resize() { - char *tmp; - unsigned long long EndSize = d->End - d->Start; - // fail is the buffer grows too big if(d->Size > 1024*1024+1) return false; + return Resize(d->Size * 2); +} +bool pkgTagFile::Resize(unsigned long long const newSize) +{ + unsigned long long const EndSize = d->End - d->Start; + // get new buffer and use it - tmp = new char[2*d->Size]; - memcpy(tmp, d->Buffer, d->Size); - d->Size = d->Size*2; - delete [] d->Buffer; - d->Buffer = tmp; + char* newBuffer = (char*)realloc(d->Buffer, sizeof(char) * newSize); + if (newBuffer == NULL) + return false; + d->Buffer = newBuffer; + d->Size = newSize; // update the start/end pointers to the new buffer d->Start = d->Buffer; @@ -152,9 +161,10 @@ bool pkgTagFile::Fill() if (d->Done == false) { // See if only a bit of the file is left - if (d->Fd.Read(d->End, d->Size - (d->End - d->Buffer),&Actual) == false) + unsigned long long const dataSize = d->Size - ((d->End - d->Buffer) + 1); + if (d->Fd.Read(d->End, dataSize, &Actual) == false) return false; - if (Actual != d->Size - (d->End - d->Buffer)) + if (Actual != dataSize || d->Fd.Eof() == true) d->Done = true; d->End += Actual; } @@ -171,8 +181,13 @@ bool pkgTagFile::Fill() for (const char *E = d->End - 1; E - d->End < 6 && (*E == '\n' || *E == '\r'); E--) if (*E == '\n') LineCount++; - for (; LineCount < 2; LineCount++) - *d->End++ = '\n'; + if (LineCount < 2) + { + if ((unsigned)(d->End - d->Buffer) >= d->Size) + Resize(d->Size + 3); + for (; LineCount < 2; LineCount++) + *d->End++ = '\n'; + } return true; } @@ -218,6 +233,16 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset) return true; } /*}}}*/ +// pkgTagSection::pkgTagSection - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgTagSection::pkgTagSection() + : Section(0), TagCount(0), d(NULL), Stop(0) +{ + memset(&Indexes, 0, sizeof(Indexes)); + memset(&AlphaIndexes, 0, sizeof(AlphaIndexes)); +} + /*}}}*/ // TagSection::Scan - Scan for the end of the header information /*{{{*/ // --------------------------------------------------------------------- /* This looks for the first double new line in the data stream. diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 4718f5101..518d3dbcd 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -84,7 +84,7 @@ class pkgTagSection Stop = this->Stop; }; - pkgTagSection() : Section(0), TagCount(0), Stop(0) {}; + pkgTagSection(); virtual ~pkgTagSection() {}; }; @@ -95,6 +95,7 @@ class pkgTagFile bool Fill(); bool Resize(); + bool Resize(unsigned long long const newSize); public: diff --git a/apt-pkg/vendorlist.cc b/apt-pkg/vendorlist.cc index ecfc7db87..602425624 100644 --- a/apt-pkg/vendorlist.cc +++ b/apt-pkg/vendorlist.cc @@ -66,7 +66,7 @@ bool pkgVendorList::CreateList(Configuration& Cnf) /*{{{*/ Configuration Block(Top); string VendorID = Top->Tag; vector <struct Vendor::Fingerprint *> *Fingerprints = new vector<Vendor::Fingerprint *>; - struct Vendor::Fingerprint *Fingerprint = new struct Vendor::Fingerprint; + struct Vendor::Fingerprint *Fingerprint = new struct Vendor::Fingerprint(); string Origin = Block.Find("Origin"); Fingerprint->Print = Block.Find("Fingerprint"); |