diff options
author | Michael Vogt <mvo@ubuntu.com> | 2013-07-02 16:53:45 +0200 |
---|---|---|
committer | Michael Vogt <mvo@ubuntu.com> | 2013-07-02 16:53:45 +0200 |
commit | 56363109dac51dffb6ec8491728e0bc934a15fa1 (patch) | |
tree | 90db7c6af4ea25028df6c2731a57b0724fc3c626 /apt-pkg | |
parent | 3599bca5211077f5456a40adb5cec1bcbee8c3ae (diff) | |
parent | 4b8528bd5749f759e924534709a620da67cd40f8 (diff) |
merged debian/sid branch from git.debian.org
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/acquire-item.cc | 13 | ||||
-rw-r--r-- | apt-pkg/acquire-worker.cc | 13 | ||||
-rw-r--r-- | apt-pkg/algorithms.cc | 23 | ||||
-rw-r--r-- | apt-pkg/algorithms.h | 7 | ||||
-rw-r--r-- | apt-pkg/cdrom.cc | 8 | ||||
-rw-r--r-- | apt-pkg/contrib/error.h | 41 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.cc | 198 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.h | 4 | ||||
-rw-r--r-- | apt-pkg/contrib/gpgv.cc | 2 | ||||
-rw-r--r-- | apt-pkg/contrib/gpgv.h | 15 | ||||
-rw-r--r-- | apt-pkg/contrib/sha2_internal.cc | 12 | ||||
-rw-r--r-- | apt-pkg/contrib/strutl.cc | 14 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.cc | 6 | ||||
-rw-r--r-- | apt-pkg/depcache.cc | 33 | ||||
-rw-r--r-- | apt-pkg/indexcopy.cc | 18 | ||||
-rw-r--r-- | apt-pkg/indexcopy.h | 10 | ||||
-rw-r--r-- | apt-pkg/orderlist.cc | 224 | ||||
-rw-r--r-- | apt-pkg/packagemanager.cc | 117 | ||||
-rw-r--r-- | apt-pkg/pkgcachegen.cc | 4 |
19 files changed, 436 insertions, 326 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index a79dfb727..46e4a7065 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1300,7 +1300,14 @@ void pkgAcqMetaIndex::RetrievalDone(string Message) /*{{{*/ string FinalFile = _config->FindDir("Dir::State::lists"); FinalFile += URItoFileName(RealURI); if (SigFile == DestFile) + { SigFile = FinalFile; + // constructor of pkgAcqMetaClearSig moved it out of the way, + // now move it back in on IMS hit for the 'old' file + string const OldClearSig = DestFile + ".reverify"; + if (RealFileExists(OldClearSig) == true) + Rename(OldClearSig, FinalFile); + } DestFile = FinalFile; } Complete = true; @@ -1606,7 +1613,11 @@ string pkgAcqMetaClearSig::Custom600Headers() struct stat Buf; if (stat(Final.c_str(),&Buf) != 0) - return "\nIndex-File: true\nFail-Ignore: true\n"; + { + Final = DestFile + ".reverify"; + if (stat(Final.c_str(),&Buf) != 0) + return "\nIndex-File: true\nFail-Ignore: true\n"; + } return "\nIndex-File: true\nFail-Ignore: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); } diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 9d90b08bc..44a84216a 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -305,7 +305,15 @@ bool pkgAcquire::Worker::RunMessages() OwnerQ->ItemDone(Itm); unsigned long long const ServerSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10); - if (TotalSize != 0 && ServerSize != TotalSize) + bool isHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || + StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); + // Using the https method the server might return 200, but the + // If-Modified-Since condition is not satsified, libcurl will + // discard the download. In this case, however, TotalSize will be + // set to the actual size of the file, while ServerSize will be set + // to 0. Therefore, if the item is marked as a hit and the + // downloaded size (ServerSize) is 0, we ignore TotalSize. + if (TotalSize != 0 && (!isHit || ServerSize != 0) && ServerSize != TotalSize) _error->Warning("Size of file %s is not what the server reported %s %llu", Owner->DestFile.c_str(), LookupTag(Message,"Size","0").c_str(),TotalSize); @@ -332,8 +340,7 @@ bool pkgAcquire::Worker::RunMessages() // Log that we are done if (Log != 0) { - if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true || - StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true) + if (isHit) { /* Hide 'hits' for local only sources - we also manage to hide gets */ diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 7fcd9f0db..85799a11b 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -648,7 +648,10 @@ void pkgProblemResolver::MakeScores() D->Type != pkgCache::Dep::Recommends)) continue; - Scores[I->ID] += abs(OldScores[D.ParentPkg()->ID]); + // Do not propagate negative scores otherwise + // an extra (-2) package might score better than an optional (-1) + if (OldScores[D.ParentPkg()->ID] > 0) + Scores[I->ID] += OldScores[D.ParentPkg()->ID]; } } @@ -842,8 +845,10 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) } while (Again == true); - if (Debug == true) - clog << "Starting" << endl; + if (Debug == true) { + clog << "Starting pkgProblemResolver with broken count: " + << Cache.BrokenCount() << endl; + } MakeScores(); @@ -871,8 +876,10 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) } } - if (Debug == true) - clog << "Starting 2" << endl; + if (Debug == true) { + clog << "Starting 2 pkgProblemResolver with broken count: " + << Cache.BrokenCount() << endl; + } /* Now consider all broken packages. For each broken package we either remove the package or fix it's problem. We do this once, it should @@ -1437,9 +1444,11 @@ bool pkgProblemResolver::ResolveByKeepInternal() return true; } /*}}}*/ -// ProblemResolver::InstallProtect - Install all protected packages /*{{{*/ +// ProblemResolver::InstallProtect - deprecated cpu-eating no-op /*{{{*/ // --------------------------------------------------------------------- -/* This is used to make sure protected packages are installed */ +/* Actions issued with FromUser bit set are protected from further + modification (expect by other calls with FromUser set) nowadays , so we + don't need to reissue actions here, they are already set in stone. */ void pkgProblemResolver::InstallProtect() { pkgDepCache::ActionGroup group(Cache); diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index aff8a68f2..7f58c8eed 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -36,6 +36,8 @@ #include <iostream> +#include <apt-pkg/macros.h> + #ifndef APT_8_CLEANER_HEADERS #include <apt-pkg/acquire.h> using std::ostream; @@ -132,9 +134,8 @@ class pkgProblemResolver /*{{{*/ // Try to resolve problems only by using keep bool ResolveByKeep(); - // Install all protected packages - void InstallProtect(); - + __deprecated void InstallProtect(); + pkgProblemResolver(pkgDepCache *Cache); ~pkgProblemResolver(); }; diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index 9a9a854bf..a5668a50a 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -829,6 +829,14 @@ bool pkgCdrom::Add(pkgCdromStatus *log) /*{{{*/ log->Update(msg.str()); log->Update(_("Copying package lists..."), STEP_COPY); } + + // check for existence and possibly create state directory for copying + string const listDir = _config->FindDir("Dir::State::lists"); + string const partialListDir = listDir + "partial/"; + if (CreateAPTDirectoryIfNeeded(_config->FindDir("Dir::State"), partialListDir) == false && + CreateAPTDirectoryIfNeeded(listDir, partialListDir) == false) + return _error->Errno("cdrom", _("List directory %spartial is missing."), listDir.c_str()); + // take care of the signatures and copy them if they are ok // (we do this before PackageCopy as it modifies "List" and "SourceList") SigVerify SignVerify; diff --git a/apt-pkg/contrib/error.h b/apt-pkg/contrib/error.h index 21c51c1be..7d09b2d4a 100644 --- a/apt-pkg/contrib/error.h +++ b/apt-pkg/contrib/error.h @@ -123,6 +123,25 @@ public: /*{{{*/ bool InsertErrno(MsgType const &type, const char* Function, const char* Description,...) __like_printf(4) __cold; + /** \brief adds an errno message with the given type + * + * args needs to be initialized with va_start and terminated + * with va_end by the caller. msgSize is also an out-parameter + * in case the msgSize was not enough to store the complete message. + * + * \param type of the error message + * \param Function which failed + * \param Description is the format string for args + * \param args list from a printf-like function + * \param errsv is the errno the error is for + * \param msgSize is the size of the char[] used to store message + * \return true if the message was added, false if not - the caller + * should call this method again in that case + */ + bool InsertErrno(MsgType type, const char* Function, + const char* Description, va_list &args, + int const errsv, size_t &msgSize); + /** \brief add an fatal error message to the list * * Most of the stuff we consider as "error" is also "fatal" for @@ -185,6 +204,22 @@ public: /*{{{*/ */ bool Insert(MsgType const &type, const char* Description,...) __like_printf(3) __cold; + /** \brief adds an error message with the given type + * + * args needs to be initialized with va_start and terminated + * with va_end by the caller. msgSize is also an out-parameter + * in case the msgSize was not enough to store the complete message. + * + * \param type of the error message + * \param Description is the format string for args + * \param args list from a printf-like function + * \param msgSize is the size of the char[] used to store message + * \return true if the message was added, false if not - the caller + * should call this method again in that case + */ + bool Insert(MsgType type, const char* Description, + va_list &args, size_t &msgSize) __cold; + /** \brief is an error in the list? * * \return \b true if an error is included in the list, \b false otherwise @@ -305,12 +340,6 @@ private: /*{{{*/ }; std::list<MsgStack> Stacks; - - bool InsertErrno(MsgType type, const char* Function, - const char* Description, va_list &args, - int const errsv, size_t &msgSize); - bool Insert(MsgType type, const char* Description, - va_list &args, size_t &msgSize); /*}}}*/ }; /*}}}*/ diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index c426293a3..61ff0031f 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -184,7 +184,8 @@ bool RunScripts(const char *Cnf) /* The caller is expected to set things so that failure causes erasure */ bool CopyFile(FileFd &From,FileFd &To) { - if (From.IsOpen() == false || To.IsOpen() == false) + if (From.IsOpen() == false || To.IsOpen() == false || + From.Failed() == true || To.Failed() == true) return false; // Buffered copy between fds @@ -881,7 +882,7 @@ bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, return Open(FileName, ReadOnly, Gzip, Perms); if (Compress == Auto && (Mode & WriteOnly) == WriteOnly) - return _error->Error("Autodetection on %s only works in ReadOnly openmode!", FileName.c_str()); + return FileFdError("Autodetection on %s only works in ReadOnly openmode!", FileName.c_str()); std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors(); std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin(); @@ -934,17 +935,17 @@ bool FileFd::Open(string FileName,unsigned int const Mode,CompressMode Compress, case Auto: case Extension: // Unreachable - return _error->Error("Opening File %s in None, Auto or Extension should be already handled?!?", FileName.c_str()); + return FileFdError("Opening File %s in None, Auto or Extension should be already handled?!?", FileName.c_str()); } for (; compressor != compressors.end(); ++compressor) if (compressor->Name == name) break; if (compressor == compressors.end()) - return _error->Error("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str()); + return FileFdError("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str()); } if (compressor == compressors.end()) - return _error->Error("Can't find a match for specified compressor mode for file %s", FileName.c_str()); + return FileFdError("Can't find a match for specified compressor mode for file %s", FileName.c_str()); return Open(FileName, Mode, *compressor, Perms); } bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Compressor const &compressor, unsigned long const Perms) @@ -953,9 +954,9 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co Flags = AutoClose; if ((Mode & WriteOnly) != WriteOnly && (Mode & (Atomic | Create | Empty | Exclusive)) != 0) - return _error->Error("ReadOnly mode for %s doesn't accept additional flags!", FileName.c_str()); + return FileFdError("ReadOnly mode for %s doesn't accept additional flags!", FileName.c_str()); if ((Mode & ReadWrite) == 0) - return _error->Error("No openmode provided in FileFd::Open for %s", FileName.c_str()); + return FileFdError("No openmode provided in FileFd::Open for %s", FileName.c_str()); if ((Mode & Atomic) == Atomic) { @@ -1001,7 +1002,7 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co close (iFd); iFd = -1; } - return _error->Errno("open",_("Could not open file %s"), FileName.c_str()); + return FileFdErrno("open",_("Could not open file %s"), FileName.c_str()); } SetCloseExec(iFd,true); @@ -1030,14 +1031,19 @@ bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compre case Xz: name = "xz"; break; case Auto: case Extension: - return _error->Error("Opening Fd %d in Auto or Extension compression mode is not supported", Fd); + if (AutoClose == true && Fd != -1) + close(Fd); + return FileFdError("Opening Fd %d in Auto or Extension compression mode is not supported", Fd); } for (; compressor != compressors.end(); ++compressor) if (compressor->Name == name) break; if (compressor == compressors.end()) - return _error->Error("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str()); - + { + if (AutoClose == true && Fd != -1) + close(Fd); + return FileFdError("Can't find a configured compressor %s for file %s", name.c_str(), FileName.c_str()); + } return OpenDescriptor(Fd, Mode, *compressor, AutoClose); } bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose) @@ -1059,11 +1065,21 @@ bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration: else iFd = Fd; this->FileName = ""; - if (OpenInternDescriptor(Mode, compressor) == false) + if (Fd == -1 || OpenInternDescriptor(Mode, compressor) == false) { - if (AutoClose) + if (iFd != -1 && ( +#ifdef HAVE_ZLIB + compressor.Name == "gzip" || +#endif +#ifdef HAVE_BZ2 + compressor.Name == "bzip2" || +#endif + AutoClose == true)) + { close (iFd); - return _error->Errno("gzdopen",_("Could not open file descriptor %d"), Fd); + iFd = -1; + } + return FileFdError(_("Could not open file descriptor %d"), Fd); } return true; } @@ -1125,10 +1141,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C ExecWait(d->compressor_pid, "FileFdCompressor", true); if ((Mode & ReadWrite) == ReadWrite) - { - Flags |= Fail; - return _error->Error("ReadWrite mode is not supported for file %s", FileName.c_str()); - } + return FileFdError("ReadWrite mode is not supported for file %s", FileName.c_str()); bool const Comp = (Mode & WriteOnly) == WriteOnly; if (Comp == false) @@ -1151,10 +1164,7 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C // Create a data pipe int Pipe[2] = {-1,-1}; if (pipe(Pipe) != 0) - { - Flags |= Fail; - return _error->Errno("pipe",_("Failed to create subprocess IPC")); - } + return FileFdErrno("pipe",_("Failed to create subprocess IPC")); for (int J = 0; J != 2; J++) SetCloseExec(Pipe[J],true); @@ -1264,14 +1274,13 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) { if (errno == EINTR) continue; - Flags |= Fail; #ifdef HAVE_ZLIB if (d != NULL && d->gz != NULL) { int err; char const * const errmsg = gzerror(d->gz, &err); if (err != Z_ERRNO) - return _error->Error("gzread: %s (%d: %s)", _("Read error"), err, errmsg); + return FileFdError("gzread: %s (%d: %s)", _("Read error"), err, errmsg); } #endif #ifdef HAVE_BZ2 @@ -1280,10 +1289,10 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) int err; char const * const errmsg = BZ2_bzerror(d->bz2, &err); if (err != BZ_IO_ERROR) - return _error->Error("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg); + return FileFdError("BZ2_bzread: %s (%d: %s)", _("Read error"), err, errmsg); } #endif - return _error->Errno("read",_("Read error")); + return FileFdErrno("read",_("Read error")); } To = (char *)To + Res; @@ -1304,9 +1313,8 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual) Flags |= HitEof; return true; } - - Flags |= Fail; - return _error->Error(_("read, still have %llu to read but none left"), Size); + + return FileFdError(_("read, still have %llu to read but none left"), Size); } /*}}}*/ // FileFd::ReadLine - Read a complete line from the file /*{{{*/ @@ -1362,14 +1370,13 @@ bool FileFd::Write(const void *From,unsigned long long Size) continue; if (Res < 0) { - Flags |= Fail; #ifdef HAVE_ZLIB if (d != NULL && d->gz != NULL) { int err; char const * const errmsg = gzerror(d->gz, &err); if (err != Z_ERRNO) - return _error->Error("gzwrite: %s (%d: %s)", _("Write error"), err, errmsg); + return FileFdError("gzwrite: %s (%d: %s)", _("Write error"), err, errmsg); } #endif #ifdef HAVE_BZ2 @@ -1378,10 +1385,10 @@ bool FileFd::Write(const void *From,unsigned long long Size) int err; char const * const errmsg = BZ2_bzerror(d->bz2, &err); if (err != BZ_IO_ERROR) - return _error->Error("BZ2_bzwrite: %s (%d: %s)", _("Write error"), err, errmsg); + return FileFdError("BZ2_bzwrite: %s (%d: %s)", _("Write error"), err, errmsg); } #endif - return _error->Errno("write",_("Write error")); + return FileFdErrno("write",_("Write error")); } From = (char *)From + Res; @@ -1393,9 +1400,8 @@ bool FileFd::Write(const void *From,unsigned long long Size) if (Size == 0) return true; - - Flags |= Fail; - return _error->Error(_("write, still have %llu to write but couldn't"), Size); + + return FileFdError(_("write, still have %llu to write but couldn't"), Size); } bool FileFd::Write(int Fd, const void *From, unsigned long long Size) { @@ -1439,13 +1445,13 @@ bool FileFd::Seek(unsigned long long To) return Skip(To - seekpos); if ((d->openmode & ReadOnly) != ReadOnly) - { - Flags |= Fail; - return _error->Error("Reopen is only implemented for read-only files!"); - } + return FileFdError("Reopen is only implemented for read-only files!"); #ifdef HAVE_BZ2 - if (d->bz2 != NULL) - BZ2_bzclose(d->bz2); + if (d->bz2 != NULL) + { + BZ2_bzclose(d->bz2); + d->bz2 = NULL; + } #endif if (iFd != -1) close(iFd); @@ -1460,17 +1466,11 @@ bool FileFd::Seek(unsigned long long To) if (lseek(d->compressed_fd, 0, SEEK_SET) != 0) iFd = d->compressed_fd; if (iFd < 0) - { - Flags |= Fail; - return _error->Error("Reopen is not implemented for pipes opened with FileFd::OpenDescriptor()!"); - } + return FileFdError("Reopen is not implemented for pipes opened with FileFd::OpenDescriptor()!"); } if (OpenInternDescriptor(d->openmode, d->compressor) == false) - { - Flags |= Fail; - return _error->Error("Seek on file %s because it couldn't be reopened", FileName.c_str()); - } + return FileFdError("Seek on file %s because it couldn't be reopened", FileName.c_str()); if (To != 0) return Skip(To); @@ -1486,10 +1486,7 @@ bool FileFd::Seek(unsigned long long To) #endif res = lseek(iFd,To,SEEK_SET); if (res != (signed)To) - { - Flags |= Fail; - return _error->Error("Unable to seek to %llu", To); - } + return FileFdError("Unable to seek to %llu", To); if (d != NULL) d->seekpos = To; @@ -1513,10 +1510,7 @@ bool FileFd::Skip(unsigned long long Over) { unsigned long long toread = std::min((unsigned long long) sizeof(buffer), Over); if (Read(buffer, toread) == false) - { - Flags |= Fail; - return _error->Error("Unable to seek ahead %llu",Over); - } + return FileFdError("Unable to seek ahead %llu",Over); Over -= toread; } return true; @@ -1530,10 +1524,7 @@ bool FileFd::Skip(unsigned long long Over) #endif res = lseek(iFd,Over,SEEK_CUR); if (res < 0) - { - Flags |= Fail; - return _error->Error("Unable to seek ahead %llu",Over); - } + return FileFdError("Unable to seek ahead %llu",Over); if (d != NULL) d->seekpos = res; @@ -1547,17 +1538,11 @@ bool FileFd::Truncate(unsigned long long To) { #if defined HAVE_ZLIB || defined HAVE_BZ2 if (d != NULL && (d->gz != NULL || d->bz2 != NULL)) - { - Flags |= Fail; - return _error->Error("Truncating compressed files is not implemented (%s)", FileName.c_str()); - } + return FileFdError("Truncating compressed files is not implemented (%s)", FileName.c_str()); #endif if (ftruncate(iFd,To) != 0) - { - Flags |= Fail; - return _error->Error("Unable to truncate to %llu",To); - } - + return FileFdError("Unable to truncate to %llu",To); + return true; } /*}}}*/ @@ -1585,10 +1570,7 @@ unsigned long long FileFd::Tell() #endif Res = lseek(iFd,0,SEEK_CUR); if (Res == (off_t)-1) - { - Flags |= Fail; - _error->Errno("lseek","Failed to determine the current file position"); - } + FileFdErrno("lseek","Failed to determine the current file position"); if (d != NULL) d->seekpos = Res; return Res; @@ -1601,10 +1583,7 @@ unsigned long long FileFd::FileSize() { struct stat Buf; if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0) - { - Flags |= Fail; - return _error->Errno("fstat","Unable to determine the file size"); - } + return FileFdErrno("fstat","Unable to determine the file size"); // for compressor pipes st_size is undefined and at 'best' zero if ((d != NULL && d->pipe == true) || S_ISFIFO(Buf.st_mode)) @@ -1614,10 +1593,7 @@ unsigned long long FileFd::FileSize() if (d != NULL) d->pipe = true; if (stat(FileName.c_str(), &Buf) != 0) - { - Flags |= Fail; - return _error->Errno("stat","Unable to determine the file size"); - } + return FileFdErrno("stat","Unable to determine the file size"); } return Buf.st_size; @@ -1659,16 +1635,10 @@ 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) - { - Flags |= Fail; - return _error->Errno("lseek","Unable to seek to end of gzipped file"); - } + return FileFdErrno("lseek","Unable to seek to end of gzipped file"); size = 0L; if (read(iFd, &size, 4) != 4) - { - Flags |= Fail; - return _error->Errno("read","Unable to read original size of gzipped file"); - } + return FileFdErrno("read","Unable to read original size of gzipped file"); #ifdef WORDS_BIGENDIAN uint32_t tmp_size = size; @@ -1678,10 +1648,7 @@ unsigned long long FileFd::Size() #endif if (lseek(iFd, oldPos, SEEK_SET) < 0) - { - Flags |= Fail; - return _error->Errno("lseek","Unable to seek in gzipped file"); - } + return FileFdErrno("lseek","Unable to seek in gzipped file"); return size; } @@ -1698,8 +1665,7 @@ time_t FileFd::ModificationTime() struct stat Buf; if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0) { - Flags |= Fail; - _error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str()); + FileFdErrno("fstat","Unable to determine the modification time of file %s", FileName.c_str()); return 0; } @@ -1712,8 +1678,7 @@ time_t FileFd::ModificationTime() d->pipe = true; if (stat(FileName.c_str(), &Buf) != 0) { - Flags |= Fail; - _error->Errno("fstat","Unable to determine the modification time of file %s", FileName.c_str()); + FileFdErrno("fstat","Unable to determine the modification time of file %s", FileName.c_str()); return 0; } } @@ -1769,11 +1734,40 @@ bool FileFd::Close() bool FileFd::Sync() { if (fsync(iFd) != 0) + return FileFdErrno("sync",_("Problem syncing the file")); + return true; +} + /*}}}*/ +// FileFd::FileFdErrno - set Fail and call _error->Errno *{{{*/ +bool FileFd::FileFdErrno(const char *Function, const char *Description,...) +{ + Flags |= Fail; + va_list args; + size_t msgSize = 400; + int const errsv = errno; + while (true) { - Flags |= Fail; - return _error->Errno("sync",_("Problem syncing the file")); + va_start(args,Description); + if (_error->InsertErrno(GlobalError::ERROR, Function, Description, args, errsv, msgSize) == false) + break; + va_end(args); } - return true; + return false; +} + /*}}}*/ +// FileFd::FileFdError - set Fail and call _error->Error *{{{*/ +bool FileFd::FileFdError(const char *Description,...) { + Flags |= Fail; + va_list args; + size_t msgSize = 400; + while (true) + { + va_start(args,Description); + if (_error->Insert(GlobalError::ERROR, Description, args, msgSize) == false) + break; + va_end(args); + } + return false; } /*}}}*/ diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 510b1c984..f8e30e6ea 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -149,6 +149,10 @@ class FileFd private: FileFdPrivate* d; bool OpenInternDescriptor(unsigned int const Mode, APT::Configuration::Compressor const &compressor); + + // private helpers to set Fail flag and call _error->Error + bool FileFdErrno(const char* Function, const char* Description,...) __like_printf(3) __cold; + bool FileFdError(const char* Description,...) __like_printf(2) __cold; }; bool RunScripts(const char *Cnf); diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc index 31db7d5fe..f47e7ea48 100644 --- a/apt-pkg/contrib/gpgv.cc +++ b/apt-pkg/contrib/gpgv.cc @@ -154,7 +154,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG, if (sigFd != -1) unlink(data); ioprintf(std::cerr, "Splitting up %s into data and signature failed", File.c_str()); - exit(EINTERNAL); + exit(112); } Args.push_back(sig); Args.push_back(data); diff --git a/apt-pkg/contrib/gpgv.h b/apt-pkg/contrib/gpgv.h index 08b10a97a..45f069058 100644 --- a/apt-pkg/contrib/gpgv.h +++ b/apt-pkg/contrib/gpgv.h @@ -23,9 +23,18 @@ /** \brief generates and run the command to verify a file with gpgv * * If File and FileSig specify the same file it is assumed that we - * deal with a clear-signed message. In that case the file will be - * rewritten to be in a good-known format without uneeded whitespaces - * and additional messages (unsigned or signed). + * deal with a clear-signed message. Note that the method will accept + * and validate files which include additional (unsigned) messages + * without complaining. Do NOT open files accepted by this method + * for reading. Use #OpenMaybeClearSignedFile to access the message + * instead to ensure you are only reading signed data. + * + * The method does not return, but has some noteable exit-codes: + * 111 signals an internal error like the inability to execute gpgv, + * 112 indicates a clear-signed file which doesn't include a message, + * which can happen if APT is run while on a network requiring + * authentication before usage (e.g. in hotels) + * All other exit-codes are passed-through from gpgv. * * @param File is the message (unsigned or clear-signed) * @param FileSig is the signature (detached or clear-signed) diff --git a/apt-pkg/contrib/sha2_internal.cc b/apt-pkg/contrib/sha2_internal.cc index 83b5a98d3..f84fb761c 100644 --- a/apt-pkg/contrib/sha2_internal.cc +++ b/apt-pkg/contrib/sha2_internal.cc @@ -632,7 +632,7 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { } /* Clean up state data: */ - MEMSET_BZERO(context, sizeof(context)); + MEMSET_BZERO(context, sizeof(*context)); usedspace = 0; } @@ -653,7 +653,7 @@ char *SHA256_End(SHA256_CTX* context, char buffer[]) { } *buffer = (char)0; } else { - MEMSET_BZERO(context, sizeof(context)); + MEMSET_BZERO(context, sizeof(*context)); } MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH); return buffer; @@ -969,7 +969,7 @@ void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) { } /* Zero out state data */ - MEMSET_BZERO(context, sizeof(context)); + MEMSET_BZERO(context, sizeof(*context)); } char *SHA512_End(SHA512_CTX* context, char buffer[]) { @@ -989,7 +989,7 @@ char *SHA512_End(SHA512_CTX* context, char buffer[]) { } *buffer = (char)0; } else { - MEMSET_BZERO(context, sizeof(context)); + MEMSET_BZERO(context, sizeof(*context)); } MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH); return buffer; @@ -1044,7 +1044,7 @@ void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) { } /* Zero out state data */ - MEMSET_BZERO(context, sizeof(context)); + MEMSET_BZERO(context, sizeof(*context)); } char *SHA384_End(SHA384_CTX* context, char buffer[]) { @@ -1064,7 +1064,7 @@ char *SHA384_End(SHA384_CTX* context, char buffer[]) { } *buffer = (char)0; } else { - MEMSET_BZERO(context, sizeof(context)); + MEMSET_BZERO(context, sizeof(*context)); } MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH); return buffer; diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 64731b482..8ce3a306f 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -759,7 +759,8 @@ bool ReadMessages(int Fd, vector<string> &List) for (char *I = Buffer; I + 1 < End; I++) { if (I[1] != '\n' || - (strncmp(I, "\n\n", 2) != 0 && strncmp(I, "\r\n\r\n", 4) != 0)) + + (I[0] != '\n' && strncmp(I, "\r\n\r\n", 4) != 0)) continue; // Pull the message out @@ -767,7 +768,7 @@ bool ReadMessages(int Fd, vector<string> &List) PartialMessage += Message; // Fix up the buffer - for (; I < End && (*I == '\r' || *I == '\n'); ++I); + for (; I < End && (*I == '\n' || *I == '\r'); ++I); End -= I-Buffer; memmove(Buffer,I,End-Buffer); I = Buffer; @@ -1484,9 +1485,12 @@ URI::operator string() if (User.empty() == false) { - Res += User; + // FIXME: Technically userinfo is permitted even less + // characters than these, but this is not conveniently + // expressed with a blacklist. + Res += QuoteString(User, ":/?#[]@"); if (Password.empty() == false) - Res += ":" + Password; + Res += ":" + QuoteString(Password, ":/?#[]@"); Res += "@"; } @@ -1525,7 +1529,6 @@ string URI::SiteOnly(const string &URI) U.User.clear(); U.Password.clear(); U.Path.clear(); - U.Port = 0; return U; } /*}}}*/ @@ -1537,7 +1540,6 @@ string URI::NoUserPassword(const string &URI) ::URI U(URI); U.User.clear(); U.Password.clear(); - U.Port = 0; return U; } /*}}}*/ diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index db86bd698..28857176b 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -219,8 +219,12 @@ MD5SumValue debListParser::Description_md5() string const value = Section.FindS("Description-md5"); if (value.empty() == true) { + std::string const desc = Description() + "\n"; + if (desc == "\n") + return MD5SumValue(); + MD5Summation md5; - md5.Add((Description() + "\n").c_str()); + md5.Add(desc.c_str()); return md5.Result(); } else if (likely(value.size() == 32)) diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 6a3e9bfc4..9f8422fec 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1004,7 +1004,7 @@ struct CompareProviders { } // higher priority seems like a good idea if (AV->Priority != BV->Priority) - return AV->Priority < BV->Priority; + return AV->Priority > BV->Priority; // prefer native architecture if (strcmp(A.Arch(), B.Arch()) != 0) { @@ -1200,16 +1200,23 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, verlist.insert(Cand); } CompareProviders comp(Start); - APT::VersionList::iterator InstVer = std::max_element(verlist.begin(), verlist.end(), comp); - if (InstVer != verlist.end()) - { + do { + APT::VersionList::iterator InstVer = std::max_element(verlist.begin(), verlist.end(), comp); + + if (InstVer == verlist.end()) + break; + pkgCache::PkgIterator InstPkg = InstVer.ParentPkg(); if(DebugAutoInstall == true) std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name() << " as " << Start.DepType() << " of " << Pkg.Name() << std::endl; - MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps); + if (MarkInstall(InstPkg, true, Depth + 1, false, ForceImportantDeps) == false) + { + verlist.erase(InstVer); + continue; + } // now check if we should consider it a automatic dependency or not if(InstPkg->CurrentVer == 0 && Pkg->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section())) { @@ -1218,7 +1225,8 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, << Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl; MarkAuto(InstPkg, false); } - } + break; + } while(true); continue; } /* Negative dependencies have no or-group @@ -1243,9 +1251,16 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, PkgState[Pkg->ID].CandidateVer != *I && MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps) == true) continue; - else if ((Start->Type == pkgCache::Dep::Conflicts || Start->Type == pkgCache::Dep::DpkgBreaks) && - MarkDelete(Pkg,false,Depth + 1, false) == false) - break; + else if (Start->Type == pkgCache::Dep::Conflicts || + Start->Type == pkgCache::Dep::DpkgBreaks) + { + if(DebugAutoInstall == true) + std::clog << OutputInDepth(Depth) + << " Removing: " << Pkg.Name() + << std::endl; + if (MarkDelete(Pkg,false,Depth + 1, false) == false) + break; + } } continue; } diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index a262ef789..1d61b974d 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -544,11 +544,9 @@ bool SigVerify::CopyMetaIndex(string CDROM, string CDName, /*{{{*/ FileFd Rel; Target.Open(TargetF,FileFd::WriteAtomic); Rel.Open(prefix + file,FileFd::ReadOnly); - if (_error->PendingError() == true) - return false; if (CopyFile(Rel,Target) == false) - return false; - + return _error->Error("Copying of '%s' for '%s' from '%s' failed", file.c_str(), CDName.c_str(), prefix.c_str()); + return true; } /*}}}*/ @@ -642,6 +640,18 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList, return true; } /*}}}*/ +// SigVerify::RunGPGV - deprecated wrapper calling ExecGPGV /*{{{*/ +bool SigVerify::RunGPGV(std::string const &File, std::string const &FileOut, + int const &statusfd, int fd[2]) { + ExecGPGV(File, FileOut, statusfd, fd); + return false; +}; +bool SigVerify::RunGPGV(std::string const &File, std::string const &FileOut, + int const &statusfd) { + ExecGPGV(File, FileOut, statusfd); + return false; +}; + /*}}}*/ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ vector<string> &List, pkgCdromStatus *log) { diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h index aa221158e..e6a07a887 100644 --- a/apt-pkg/indexcopy.h +++ b/apt-pkg/indexcopy.h @@ -100,15 +100,9 @@ class SigVerify /*{{{*/ std::vector<std::string> PkgList,std::vector<std::string> SrcList); __deprecated static bool RunGPGV(std::string const &File, std::string const &FileOut, - int const &statusfd, int fd[2]) { - ExecGPGV(File, FileOut, statusfd, fd); - return false; - }; + int const &statusfd, int fd[2]); __deprecated static bool RunGPGV(std::string const &File, std::string const &FileOut, - int const &statusfd = -1) { - ExecGPGV(File, FileOut, statusfd); - return false; - }; + int const &statusfd = -1); }; /*}}}*/ diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc index 80d8fd490..984ae1d10 100644 --- a/apt-pkg/orderlist.cc +++ b/apt-pkg/orderlist.cc @@ -301,9 +301,8 @@ bool pkgOrderList::OrderConfigure() /* Higher scores order earlier */ int pkgOrderList::Score(PkgIterator Pkg) { - static int const ScoreDelete = _config->FindI("OrderList::Score::Delete", 500); - - // Removal is always done first + // Removals should be done after we dealt with essentials + static int const ScoreDelete = _config->FindI("OrderList::Score::Delete", 100); if (Cache[Pkg].Delete() == true) return ScoreDelete; @@ -893,149 +892,136 @@ bool pkgOrderList::DepConfigure(DepIterator D) /*}}}*/ // OrderList::DepRemove - Removal ordering /*{{{*/ // --------------------------------------------------------------------- -/* Removal visits all reverse depends. It considers if the dependency - of the Now state version to see if it is okay with removing this - package. This check should always fail, but is provided for symetery - with the other critical handlers. - - Loops are preprocessed and logged. Removal loops can also be - detected in the critical handler. They are characterized by an - old version of A depending on B but the new version of A conflicting - with B, thus either A or B must break to install. */ -bool pkgOrderList::DepRemove(DepIterator D) +/* Checks all given dependencies if they are broken by the remove of a + package and if so fix it by visiting another provider or or-group + member to ensure that the dependee keeps working which is especially + important for Immediate packages like e.g. those depending on an + awk implementation. If the dependency can't be fixed with another + package this means an upgrade of the package will solve the problem. */ +bool pkgOrderList::DepRemove(DepIterator Broken) { - if (D.Reverse() == false) + if (Broken.Reverse() == false) return true; - for (; D.end() == false; ++D) - if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends) + + for (; Broken.end() == false; ++Broken) + { + if (Broken->Type != pkgCache::Dep::Depends && + Broken->Type != pkgCache::Dep::PreDepends) + continue; + + PkgIterator BrokenPkg = Broken.ParentPkg(); + // uninstalled packages can't break via a remove + if (BrokenPkg->CurrentVer == 0) + continue; + + // if its already added, we can't do anything useful + if (IsFlag(BrokenPkg, AddPending) == true || IsFlag(BrokenPkg, Added) == true) + continue; + + // if the dependee is going to be removed, visit it now + if (Cache[BrokenPkg].Delete() == true) + return VisitNode(BrokenPkg, "Remove-Dependee"); + + // The package stays around, so find out how this is possible + for (DepIterator D = BrokenPkg.CurrentVer().DependsList(); D.end() == false;) { - // Duplication elimination, consider the current version only - if (D.ParentPkg().CurrentVer() != D.ParentVer()) + // only important or-groups need fixing + if (D->Type != pkgCache::Dep::Depends && + D->Type != pkgCache::Dep::PreDepends) + { + ++D; continue; + } - /* We wish to see if the dep on the parent package is okay - in the removed (install) state of the target pkg. */ - bool tryFixDeps = false; - if (CheckDep(D) == true) + // Start is the beginning of the or-group, D is the first one after or + DepIterator Start = D; + bool foundBroken = false; + for (bool LastOR = true; D.end() == false && LastOR == true; ++D) { - // We want to catch loops with the code below. - if (IsFlag(D.ParentPkg(),AddPending) == false) - continue; + LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; + if (D == Broken) + foundBroken = true; } - else - tryFixDeps = true; - // This is the loop detection - if (IsFlag(D.ParentPkg(),Added) == true || - IsFlag(D.ParentPkg(),AddPending) == true) - { - if (IsFlag(D.ParentPkg(),AddPending) == true) - AddLoop(D); + // this or-group isn't the broken one: keep searching + if (foundBroken == false) continue; + + // iterate over all members of the or-group searching for a ready replacement + bool readyReplacement = false; + for (DepIterator OrMember = Start; OrMember != D && readyReplacement == false; ++OrMember) + { + Version ** Replacements = OrMember.AllTargets(); + for (Version **R = Replacements; *R != 0; ++R) + { + VerIterator Ver(Cache,*R); + // only currently installed packages can be a replacement + PkgIterator RPkg = Ver.ParentPkg(); + if (RPkg.CurrentVer() != Ver) + continue; + + // packages going to be removed can't be a replacement + if (Cache[RPkg].Delete() == true) + continue; + + readyReplacement = true; + break; + } + delete[] Replacements; } - if (tryFixDeps == true) + // something else is ready to take over, do nothing + if (readyReplacement == true) + continue; + + // see if we can visit a replacement + bool visitReplacement = false; + for (DepIterator OrMember = Start; OrMember != D && visitReplacement == false; ++OrMember) { - for (pkgCache::DepIterator F = D.ParentPkg().CurrentVer().DependsList(); - F.end() == false; ++F) + Version ** Replacements = OrMember.AllTargets(); + for (Version **R = Replacements; *R != 0; ++R) { - if (F->Type != pkgCache::Dep::Depends && F->Type != pkgCache::Dep::PreDepends) + VerIterator Ver(Cache,*R); + // consider only versions we plan to install + PkgIterator RPkg = Ver.ParentPkg(); + if (Cache[RPkg].Install() == false || Cache[RPkg].InstallVer != Ver) continue; - // Check the Providers - if (F.TargetPkg()->ProvidesList != 0) - { - pkgCache::PrvIterator Prov = F.TargetPkg().ProvidesList(); - for (; Prov.end() == false; ++Prov) - { - pkgCache::PkgIterator const P = Prov.OwnerPkg(); - if (IsFlag(P, InList) == true && - IsFlag(P, AddPending) == true && - IsFlag(P, Added) == false && - Cache[P].InstallVer == 0) - break; - } - if (Prov.end() == false) - for (pkgCache::PrvIterator Prv = F.TargetPkg().ProvidesList(); - Prv.end() == false; ++Prv) - { - pkgCache::PkgIterator const P = Prv.OwnerPkg(); - if (IsFlag(P, InList) == true && - IsFlag(P, AddPending) == false && - Cache[P].InstallVer != 0 && - VisitNode(P, "Remove-P") == true) - { - Flag(P, Immediate); - tryFixDeps = false; - break; - } - } - if (tryFixDeps == false) - break; - } - // Check for Or groups - if ((F->CompareOp & pkgCache::Dep::Or) != pkgCache::Dep::Or) + // loops are not going to help us, so don't create them + if (IsFlag(RPkg, AddPending) == true) continue; - // Lets see if the package is part of the Or group - pkgCache::DepIterator S = F; - for (; S.end() == false; ++S) + + if (IsMissing(RPkg) == true) + continue; + + visitReplacement = true; + if (IsFlag(BrokenPkg, Immediate) == false) { - if (S.TargetPkg() == D.TargetPkg()) + if (VisitNode(RPkg, "Remove-Rep") == true) break; - if ((S->CompareOp & pkgCache::Dep::Or) != pkgCache::Dep::Or || - CheckDep(S)) // Or group is satisfied by another package - for (;S.end() == false; ++S); } - if (S.end() == true) - continue; - // skip to the end of the or group - for (;S.end() == false && (S->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or; ++S); - ++S; - // The soon to be removed is part of the Or group - // start again in the or group and find something which will serve as replacement - for (; F.end() == false && F != S; ++F) + else { - if (IsFlag(F.TargetPkg(), InList) == true && - IsFlag(F.TargetPkg(), AddPending) == false && - Cache[F.TargetPkg()].InstallVer != 0 && - VisitNode(F.TargetPkg(), "Remove-Target") == true) - { - Flag(F.TargetPkg(), Immediate); - tryFixDeps = false; + Flag(RPkg, Immediate); + if (VisitNode(RPkg, "Remove-ImmRep") == true) break; - } - else if (F.TargetPkg()->ProvidesList != 0) - { - pkgCache::PrvIterator Prv = F.TargetPkg().ProvidesList(); - for (; Prv.end() == false; ++Prv) - { - if (IsFlag(Prv.OwnerPkg(), InList) == true && - IsFlag(Prv.OwnerPkg(), AddPending) == false && - Cache[Prv.OwnerPkg()].InstallVer != 0 && - VisitNode(Prv.OwnerPkg(), "Remove-Owner") == true) - { - Flag(Prv.OwnerPkg(), Immediate); - tryFixDeps = false; - break; - } - } - if (Prv.end() == false) - break; - } } - if (tryFixDeps == false) - break; + visitReplacement = false; } + delete[] Replacements; } - - // Skip over missing files - if (IsMissing(D.ParentPkg()) == true) + if (visitReplacement == true) continue; - - if (VisitNode(D.ParentPkg(), "Remove-Parent") == false) + + // the broken package in current version can't be fixed, so install new version + if (IsMissing(BrokenPkg) == true) + break; + + if (VisitNode(BrokenPkg, "Remove-Upgrade") == false) return false; } - + } + return true; } /*}}}*/ diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 9848ac1b0..8c0d2e855 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -340,6 +340,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) bool Bad = false, Changed = false; const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 5000); unsigned int i=0; + std::list<DepIterator> needConfigure; do { Changed = false; @@ -353,7 +354,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) continue; Bad = true; - // Search for dependencies which are unpacked but aren't configured yet (maybe loops) + // Check for dependencies that have not been unpacked, probably due to loops. for (DepIterator Cur = Start; true; ++Cur) { SPtrArray<Version *> VList = Cur.AllTargets(); @@ -373,51 +374,66 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) } // Check if the version that is going to be installed will satisfy the dependency - if (Cache[DepPkg].InstallVer != *I) + if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false) continue; - if (List->IsFlag(DepPkg,pkgOrderList::UnPacked)) + if (PkgLoop == true) { - if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop) - { - // This dependency has already been dealt with by another SmartConfigure on Pkg - Bad = false; - break; - } - /* Check for a loop to prevent one forming - If A depends on B and B depends on A, SmartConfigure will - just hop between them if this is not checked. Dont remove the - loop flag after finishing however as loop is already set. - This means that there is another SmartConfigure call for this - package and it will remove the loop flag */ + if (Debug) + std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl; + Bad = false; + break; + } + else + { + if (Debug) + clog << OutputInDepth(Depth) << "Unpacking " << DepPkg.FullName() << " to avoid loop " << Cur << endl; if (PkgLoop == false) List->Flag(Pkg,pkgOrderList::Loop); - if (SmartConfigure(DepPkg, Depth + 1) == true) + if (SmartUnPack(DepPkg, true, Depth + 1) == true) { Bad = false; if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false) - Changed = true; + Changed = true; } if (PkgLoop == false) - List->RmFlag(Pkg,pkgOrderList::Loop); - // If SmartConfigure was succesfull, Bad is false, so break + List->RmFlag(Pkg,pkgOrderList::Loop); if (Bad == false) break; } - else if (List->IsFlag(DepPkg,pkgOrderList::Configured)) - { - Bad = false; - break; - } } - if (Cur == End) + + if (Cur == End || Bad == false) break; - } + } if (Bad == false) continue; - // Check for dependencies that have not been unpacked, probably due to loops. + needConfigure.push_back(Start); + } + if (i++ > max_loops) + return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (1) for %s, aborting", Pkg.FullName().c_str()); + } while (Changed == true); + + Bad = false, Changed = false, i = 0; + do + { + Changed = false; + for (std::list<DepIterator>::const_iterator D = needConfigure.begin(); D != needConfigure.end(); ++D) + { + // Compute a single dependency element (glob or) without modifying D + pkgCache::DepIterator Start, End; + { + pkgCache::DepIterator Discard = *D; + Discard.GlobOr(Start,End); + } + + if (End->Type != pkgCache::Dep::Depends) + continue; + Bad = true; + + // Search for dependencies which are unpacked but aren't configured yet (maybe loops) for (DepIterator Cur = Start; true; ++Cur) { SPtrArray<Version *> VList = Cur.AllTargets(); @@ -428,44 +444,53 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) PkgIterator DepPkg = Ver.ParentPkg(); // Check if the version that is going to be installed will satisfy the dependency - if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false) + if (Cache[DepPkg].InstallVer != *I) continue; - if (PkgLoop == true) - { - if (Debug) - std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl; - Bad = false; - break; - } - else + if (List->IsFlag(DepPkg,pkgOrderList::UnPacked)) { - if (Debug) - clog << OutputInDepth(Depth) << "Unpacking " << DepPkg.FullName() << " to avoid loop " << Cur << endl; + if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop) + { + // This dependency has already been dealt with by another SmartConfigure on Pkg + Bad = false; + break; + } + /* Check for a loop to prevent one forming + If A depends on B and B depends on A, SmartConfigure will + just hop between them if this is not checked. Dont remove the + loop flag after finishing however as loop is already set. + This means that there is another SmartConfigure call for this + package and it will remove the loop flag */ if (PkgLoop == false) List->Flag(Pkg,pkgOrderList::Loop); - if (SmartUnPack(DepPkg, true, Depth + 1) == true) + if (SmartConfigure(DepPkg, Depth + 1) == true) { Bad = false; if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false) - Changed = true; + Changed = true; } if (PkgLoop == false) - List->RmFlag(Pkg,pkgOrderList::Loop); + List->RmFlag(Pkg,pkgOrderList::Loop); + // If SmartConfigure was succesfull, Bad is false, so break if (Bad == false) break; } + else if (List->IsFlag(DepPkg,pkgOrderList::Configured)) + { + Bad = false; + break; + } } - - if (Cur == End) + if (Cur == End || Bad == false) break; - } + } + if (Bad == true && Changed == false && Debug == true) - std::clog << OutputInDepth(Depth) << "Could not satisfy " << Start << std::endl; + std::clog << OutputInDepth(Depth) << "Could not satisfy " << *D << std::endl; } if (i++ > max_loops) - return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack for %s, aborting", Pkg.FullName().c_str()); + return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (2) for %s, aborting", Pkg.FullName().c_str()); } while (Changed == true); if (Bad) { diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 3f10b6c40..7ce7aba7b 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -296,6 +296,8 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator // Find the right version to write the description MD5SumValue CurMd5 = List.Description_md5(); + if (CurMd5.Value().empty() == true || List.Description().empty() == true) + return true; std::string CurLang = List.DescriptionLanguage(); for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) @@ -480,7 +482,7 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator /* Record the Description (it is not translated) */ MD5SumValue CurMd5 = List.Description_md5(); - if (CurMd5.Value().empty() == true) + if (CurMd5.Value().empty() == true || List.Description().empty() == true) return true; std::string CurLang = List.DescriptionLanguage(); |