diff options
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/acquire-item.cc | 111 | ||||
-rw-r--r-- | apt-pkg/acquire-item.h | 8 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.cc | 43 | ||||
-rw-r--r-- | apt-pkg/contrib/gpgv.cc | 23 | ||||
-rw-r--r-- | apt-pkg/contrib/hashes.cc | 2 | ||||
-rw-r--r-- | apt-pkg/contrib/hashes.h | 2 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.cc | 8 | ||||
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 24 | ||||
-rw-r--r-- | apt-pkg/depcache.cc | 3 | ||||
-rw-r--r-- | apt-pkg/packagemanager.cc | 51 |
10 files changed, 218 insertions, 57 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 30743addf..4ddab943c 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -999,7 +999,7 @@ string pkgAcqIndex::Custom600Headers() string msg = "\nIndex-File: true"; // FIXME: this really should use "IndexTarget::IsOptional()" but that // seems to be difficult without breaking ABI - if (ShortDesc().find("Translation") != 0) + if (ShortDesc().find("Translation") != std::string::npos) msg += "\nFail-Ignore: true"; struct stat Buf; if (stat(Final.c_str(),&Buf) == 0) @@ -1028,6 +1028,31 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/ Item::Failed(Message,Cnf); } /*}}}*/ +// pkgAcqIndex::GetFinalFilename - Return the full final file path /*{{{*/ +std::string pkgAcqIndex::GetFinalFilename(std::string const &URI, + std::string const &compExt) +{ + std::string FinalFile = _config->FindDir("Dir::State::lists"); + FinalFile += URItoFileName(URI); + if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz") + FinalFile += ".gz"; + return FinalFile; +} + /*}}}*/ +// AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit /*{{{*/ +void pkgAcqIndex::ReverifyAfterIMS(std::string const &FileName) +{ + std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' ')); + if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz") + DestFile += ".gz"; + + string FinalFile = GetFinalFilename(RealURI, compExt); + Rename(FinalFile, FileName); + Decompression = true; + Desc.URI = "copy:" + FileName; + QueueURI(Desc); +} + /*}}}*/ // AcqIndex::Done - Finished a fetch /*{{{*/ // --------------------------------------------------------------------- /* This goes through a number of states.. On the initial fetch the @@ -1039,6 +1064,7 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, pkgAcquire::MethodConfig *Cfg) { Item::Done(Message,Size,Hash,Cfg); + std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' ')); if (Decompression == true) { @@ -1050,6 +1076,7 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, if (!ExpectedHash.empty() && ExpectedHash.toStr() != Hash) { + Desc.URI = RealURI; RenameOnError(HashSumMismatch); return; } @@ -1058,9 +1085,9 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, * have a Package field) (LP: #346386) (Closes: #627642) */ if (Verify == true) { - FileFd fd(DestFile, FileFd::ReadOnly); + FileFd fd(DestFile, FileFd::ReadOnlyGzip); // Only test for correctness if the file is not empty (empty is ok) - if (fd.FileSize() > 0) + if (fd.Size() > 0) { pkgTagSection sec; pkgTagFile tag(&fd); @@ -1075,8 +1102,7 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, } // Done, move it into position - string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI); + string FinalFile = GetFinalFilename(RealURI, compExt); Rename(DestFile,FinalFile); chmod(FinalFile.c_str(),0644); @@ -1084,7 +1110,9 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, will work OK */ DestFile = _config->FindDir("Dir::State::lists") + "partial/"; DestFile += URItoFileName(RealURI); - + if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz") + DestFile += ".gz"; + // Remove the compressed version. if (Erase == true) unlink(DestFile.c_str()); @@ -1098,9 +1126,6 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, string FileName = LookupTag(Message,"Alt-Filename"); if (FileName.empty() == false) { - // The files timestamp matches - if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true) - return; Decompression = true; Local = true; DestFile += ".decomp"; @@ -1117,33 +1142,36 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash, ErrorText = "Method gave a blank filename"; } - std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' ')); - - // The files timestamp matches - if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) { - if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz") - // Update DestFile for .gz suffix so that the clean operation keeps it - DestFile += ".gz"; - return; - } - if (FileName == DestFile) Erase = true; else Local = true; - + + // do not reverify cdrom sources as apt-cdrom may rewrite the Packages + // file when its doing the indexcopy + if (RealURI.substr(0,6) == "cdrom:" && + StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) + return; + + // The files timestamp matches + if (!Local && StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) + { + ReverifyAfterIMS(FileName); + return; + } + string decompProg; - // If we enable compressed indexes and already have gzip, keep it - if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz" && !Local) { - string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI) + ".gz"; - Rename(DestFile,FinalFile); - chmod(FinalFile.c_str(),0644); - - // Update DestFile for .gz suffix so that the clean operation keeps it - DestFile = _config->FindDir("Dir::State::lists") + "partial/"; + // If we enable compressed indexes, queue for hash verification + if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz" && !Local) + { + DestFile = _config->FindDir("Dir::State::lists"); DestFile += URItoFileName(RealURI) + ".gz"; + + Decompression = true; + Desc.URI = "copy:" + FileName; + QueueURI(Desc); + return; } @@ -1187,6 +1215,9 @@ string pkgAcqIndexTrans::Custom600Headers() string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(RealURI); + if (_config->FindB("Acquire::GzipIndexes",false)) + Final += ".gz"; + struct stat Buf; if (stat(Final.c_str(),&Buf) != 0) return "\nFail-Ignore: true\nIndex-File: true"; @@ -1516,6 +1547,28 @@ void pkgAcqMetaIndex::AuthDone(string Message) /*{{{*/ std::cerr << "Signature verification succeeded: " << DestFile << std::endl; + // do not trust any previously unverified content that we may have + string LastGoodSigFile = _config->FindDir("Dir::State::lists").append("partial/").append(URItoFileName(RealURI)); + if (DestFile != SigFile) + LastGoodSigFile.append(".gpg"); + LastGoodSigFile.append(".reverify"); + if(IMSHit == false && RealFileExists(LastGoodSigFile) == false) + { + for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin(); + Target != IndexTargets->end(); + ++Target) + { + // remove old indexes + std::string index = _config->FindDir("Dir::State::lists") + + URItoFileName((*Target)->URI); + unlink(index.c_str()); + // and also old gzipindexes + index += ".gz"; + unlink(index.c_str()); + } + } + + // Download further indexes with verification QueueIndexes(true); diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index f48d2a0d7..54e3b92b3 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -713,6 +713,14 @@ class pkgAcqIndex : public pkgAcquire::Item */ std::string CompressionExtension; + /** \brief Get the full pathname of the final file for the given URI + */ + std::string GetFinalFilename(std::string const &URI, + std::string const &compExt); + + /** \brief Schedule file for verification after a IMS hit */ + void ReverifyAfterIMS(std::string const &FileName); + public: // Specialized action members diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 69a675648..3d4276f34 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -781,11 +781,26 @@ pid_t ExecFork(std::set<int> KeepFDs) signal(SIGCONT,SIG_DFL); signal(SIGTSTP,SIG_DFL); - // Close all of our FDs - just in case - for (int K = 3; K != sysconf(_SC_OPEN_MAX); K++) + DIR *dir = opendir("/proc/self/fd"); + if (dir != NULL) { - if(KeepFDs.find(K) == KeepFDs.end()) - fcntl(K,F_SETFD,FD_CLOEXEC); + struct dirent *ent; + while ((ent = readdir(dir))) + { + int fd = atoi(ent->d_name); + // If fd > 0, it was a fd number and not . or .. + if (fd >= 3 && KeepFDs.find(fd) == KeepFDs.end()) + fcntl(fd,F_SETFD,FD_CLOEXEC); + } + closedir(dir); + } else { + long ScOpenMax = sysconf(_SC_OPEN_MAX); + // Close all of our FDs - just in case + for (int K = 3; K != ScOpenMax; K++) + { + if(KeepFDs.find(K) == KeepFDs.end()) + fcntl(K,F_SETFD,FD_CLOEXEC); + } } } @@ -1574,18 +1589,34 @@ bool FileFd::Write(const void *From,unsigned long long Size) size_t const n = sizeof(d->lzma->buffer)/sizeof(d->lzma->buffer[0]) - d->lzma->stream.avail_out; size_t const m = (n == 0) ? 0 : fwrite(d->lzma->buffer, 1, n, d->lzma->file); if (m != n) + { Res = -1; + errno = 0; + } else + { Res = Size - d->lzma->stream.avail_in; + if (Res == 0) + { + // lzma run was okay, but produced no output… + Res = -1; + errno = EINTR; + } + } } #endif else Res = write(iFd,From,Size); - if (Res < 0 && errno == EINTR) - continue; if (Res < 0) { + if (errno == EINTR) + { + // trick the while-loop into running again + Res = 1; + errno = 0; + continue; + } if (false) /* dummy so that the rest can be 'else if's */; #ifdef HAVE_ZLIB diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc index f24dd9640..0d74050cb 100644 --- a/apt-pkg/contrib/gpgv.cc +++ b/apt-pkg/contrib/gpgv.cc @@ -247,6 +247,20 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG, } /*}}}*/ // SplitClearSignedFile - split message into data/signature /*{{{*/ +static int GetLineErrno(char **lineptr, size_t *n, FILE *stream, std::string const &InFile) +{ + int result; + + errno = 0; + result = getline(lineptr, n, stream); + if (errno != 0) + { + _error->Errno("getline", "Could not read from %s", InFile.c_str()); + return -1; + } + + return result; +} bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, std::vector<std::string> * const ContentHeader, FileFd * const SignatureFile) { @@ -262,7 +276,8 @@ bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, char *buf = NULL; size_t buf_size = 0; - while (getline(&buf, &buf_size, in) != -1) + _error->PushToStack(); + while (GetLineErrno(&buf, &buf_size, in, InFile) != -1) { _strrstrip(buf); if (found_message_start == false) @@ -324,6 +339,12 @@ bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, } fclose(in); + // An error occured during reading - propagate it up + bool const hasErrored = _error->PendingError(); + _error->MergeWithStack(); + if (hasErrored) + return false; + if (found_signature == true) return _error->Error("Signature in file %s wasn't closed", InFile.c_str()); diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 15f83615d..1fce0d75f 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -133,7 +133,7 @@ bool Hashes::AddFD(int const Fd,unsigned long long Size, bool const addMD5, bool const addSHA1, bool const addSHA256, bool const addSHA512) { unsigned char Buf[64*64]; - bool const ToEOF = (Size == UntilEOF); + bool const ToEOF = (Size == 0); while (Size != 0 || ToEOF) { unsigned long long n = sizeof(Buf); diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index 7a62f8a8f..5cd1af03b 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -78,8 +78,6 @@ class Hashes SHA256Summation SHA256; SHA512Summation SHA512; - static const int UntilEOF = 0; - inline bool Add(const unsigned char *Data,unsigned long long Size) { return MD5.Add(Data,Size) && SHA1.Add(Data,Size) && SHA256.Add(Data,Size) && SHA512.Add(Data,Size); diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index a1bcfb710..02b9cb239 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -145,7 +145,8 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/ bool debListParser::NewVersion(pkgCache::VerIterator &Ver) { // Parse the section - Ver->Section = UniqFindTagWrite("Section"); + unsigned long const idxSection = UniqFindTagWrite("Section"); + Ver->Section = idxSection; Ver->MultiArch = ParseMultiArch(true); // Archive Size Ver->Size = Section.FindULL("Size"); @@ -260,7 +261,10 @@ bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver) { if (Pkg->Section == 0) - Pkg->Section = UniqFindTagWrite("Section"); + { + unsigned long const idxSection = UniqFindTagWrite("Section"); + Pkg->Section = idxSection; + } string const static myArch = _config->Find("APT::Architecture"); // Possible values are: "all", "native", "installed" and "none" diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index e410594df..43c5214d4 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -621,15 +621,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line) { if(action == "error") { - d->progress->Error(list[1], PackagesDone, PackagesTotal, + d->progress->Error(pkgname, PackagesDone, PackagesTotal, list[3]); pkgFailures++; - WriteApportReport(list[1].c_str(), list[3].c_str()); + WriteApportReport(pkgname.c_str(), list[3].c_str()); return; } else if(action == "conffile-prompt") { - d->progress->ConffilePrompt(list[1], PackagesDone, PackagesTotal, + d->progress->ConffilePrompt(pkgname, PackagesDone, PackagesTotal, list[3]); return; } @@ -1053,15 +1053,14 @@ void pkgDPkgPM::StartPtyMagic() } // setup the pty and stuff - struct winsize win; + struct winsize win; - // if tcgetattr for both stdin/stdout returns 0 (no error) - // we do the pty magic + // if tcgetattr does not return zero there was a error + // and we do not do any pty magic _error->PushToStack(); - if (tcgetattr(STDIN_FILENO, &d->tt) == 0 && - tcgetattr(STDOUT_FILENO, &d->tt) == 0) + if (tcgetattr(STDOUT_FILENO, &d->tt) == 0) { - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) < 0) + if (ioctl(1, TIOCGWINSZ, (char *)&win) < 0) { _error->Errno("ioctl", _("ioctl(TIOCGWINSZ) failed")); } else if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0) @@ -1667,9 +1666,10 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) // do not report dpkg I/O errors, this is a format string, so we compare // the prefix and the suffix of the error with the dpkg error message vector<string> io_errors; - io_errors.push_back(string("failed to read on buffer copy for %s")); - io_errors.push_back(string("failed in write on buffer copy for %s")); - io_errors.push_back(string("short read on buffer copy for %s")); + io_errors.push_back(string("failed to read")); + io_errors.push_back(string("failed to write")); + io_errors.push_back(string("failed to seek")); + io_errors.push_back(string("unexpected end of file or stream")); for (vector<string>::iterator I = io_errors.begin(); I != io_errors.end(); ++I) { diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 19a6e0d7e..30b1f8543 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1225,7 +1225,8 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, 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())) + if(InstPkg->CurrentVer == 0 && P.InstVerIter(*this)->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", P.InstVerIter(*this).Section())) + { if(DebugAutoInstall == true) std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct " diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 5d6bc6bd2..58ce73d5c 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -349,6 +349,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) std::list<DepIterator> needConfigure; do { + // Check each dependency and see if anything needs to be done + // so that it can be configured Changed = false; for (DepIterator D = instVer.DependsList(); D.end() == false; ) { @@ -356,11 +358,12 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) pkgCache::DepIterator Start, End; D.GlobOr(Start,End); - if (End->Type != pkgCache::Dep::Depends) + if (End->Type != pkgCache::Dep::Depends && End->Type != pkgCache::Dep::PreDepends) continue; Bad = true; - // Check for dependencies that have not been unpacked, probably due to loops. + // the first pass checks if we its all good, i.e. if we have + // to do anything at all for (DepIterator Cur = Start; true; ++Cur) { SPtrArray<Version *> VList = Cur.AllTargets(); @@ -390,6 +393,47 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) Bad = false; break; } + } + + if (Cur == End || Bad == false) + break; + } + + // this dependency is in a good state, so we can stop + if (Bad == false) + { + if (Debug) + std::clog << OutputInDepth(Depth) << "Found ok dep " << D.TargetPkg() << std::endl; + continue; + } + + // Check for dependencies that have not been unpacked, + // probably due to loops. + for (DepIterator Cur = Start; true; ++Cur) + { + SPtrArray<Version *> VList = Cur.AllTargets(); + + for (Version **I = VList; *I != 0; ++I) + { + VerIterator Ver(Cache,*I); + PkgIterator DepPkg = Ver.ParentPkg(); + + // Check if the current version of the package is available and will satisfy this dependency + if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true && + List->IsFlag(DepPkg,pkgOrderList::Removed) == false && + DepPkg.State() == PkgIterator::NeedsNothing) + continue; + + // Check if the version that is going to be installed will satisfy the dependency + if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false) + continue; + + if (PkgLoop == true) + { + if (Debug) + std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl; + Bad = false; + } else { if (Debug) @@ -422,6 +466,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (1) for %s, aborting", Pkg.FullName().c_str()); } while (Changed == true); + // now go over anything that needs configuring Bad = false, Changed = false, i = 0; do { @@ -435,7 +480,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) Discard.GlobOr(Start,End); } - if (End->Type != pkgCache::Dep::Depends) + if (End->Type != pkgCache::Dep::Depends && End->Type != pkgCache::Dep::PreDepends) continue; Bad = true; |