diff options
author | Michael Vogt <michael.vogt@ubuntu.com> | 2013-04-30 10:44:16 +0200 |
---|---|---|
committer | Michael Vogt <michael.vogt@ubuntu.com> | 2013-04-30 10:44:16 +0200 |
commit | 3599bca5211077f5456a40adb5cec1bcbee8c3ae (patch) | |
tree | 221627b7ef4e3d6d294fbaaab425f2400734bd93 /apt-pkg | |
parent | 6029901a2cf49aac035590960d84572b56f28933 (diff) | |
parent | b5595da902e62af7c295f1603ae5b43ba4cef281 (diff) |
merged from the debian-sid branch
Diffstat (limited to 'apt-pkg')
34 files changed, 809 insertions, 348 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 665dd427e..a79dfb727 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -560,7 +560,7 @@ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, Desc.Owner = this; Desc.ShortDesc = ShortDesc; - if(available_patches.size() == 0) + if(available_patches.empty() == true) { // we are done (yeah!) Finish(true); @@ -1514,22 +1514,19 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) if (AuthPass == true) { // gpgv method failed, if we have a good signature - string LastGoodSigFile = _config->FindDir("Dir::State::lists"); - if (DestFile == SigFile) - LastGoodSigFile.append(URItoFileName(RealURI)); - else - LastGoodSigFile.append("partial/").append(URItoFileName(RealURI)).append(".gpg.reverify"); + string LastGoodSigFile = _config->FindDir("Dir::State::lists").append("partial/").append(URItoFileName(RealURI)); + if (DestFile != SigFile) + LastGoodSigFile.append(".gpg"); + LastGoodSigFile.append(".reverify"); if(FileExists(LastGoodSigFile)) { + string VerifiedSigFile = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); if (DestFile != SigFile) - { - string VerifiedSigFile = _config->FindDir("Dir::State::lists") + - URItoFileName(RealURI) + ".gpg"; - Rename(LastGoodSigFile,VerifiedSigFile); - } + VerifiedSigFile.append(".gpg"); + Rename(LastGoodSigFile, VerifiedSigFile); Status = StatTransientNetworkError; - _error->Warning(_("A error occurred during the signature " + _error->Warning(_("An error occurred during the signature " "verification. The repository is not updated " "and the previous index files will be used. " "GPG error: %s: %s\n"), @@ -1588,6 +1585,15 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner, /*{{{*/ MetaSigURI(MetaSigURI), MetaSigURIDesc(MetaSigURIDesc), MetaSigShortDesc(MetaSigShortDesc) { SigFile = DestFile; + + // 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) + { + string const LastGoodSig = DestFile + ".reverify"; + Rename(Final,LastGoodSig); + } } /*}}}*/ // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ @@ -1654,7 +1660,7 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources, assumption here that all the available sources for this version share the same extension.. */ // Skip not source sources, they do not have file fields. - for (; Vf.end() == false; Vf++) + for (; Vf.end() == false; ++Vf) { if ((Vf.File()->Flags & pkgCache::Flag::NotSource) != 0) continue; @@ -1741,7 +1747,7 @@ bool pkgAcqArchive::QueueNext() { if(stringcasecmp(ForceHash, "sha512") == 0) ExpectedHash = HashString("SHA512", Parse.SHA512Hash()); - if(stringcasecmp(ForceHash, "sha256") == 0) + else if(stringcasecmp(ForceHash, "sha256") == 0) ExpectedHash = HashString("SHA256", Parse.SHA256Hash()); else if (stringcasecmp(ForceHash, "sha1") == 0) ExpectedHash = HashString("SHA1", Parse.SHA1Hash()); diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 8cd9d4c6e..7fcd9f0db 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -550,11 +550,14 @@ void pkgProblemResolver::MakeScores() unsigned long Size = Cache.Head().PackageCount; memset(Scores,0,sizeof(*Scores)*Size); - // Important Required Standard Optional Extra + // 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) int PrioMap[] = { 0, - _config->FindI("pkgProblemResolver::Scores::Important",3), - _config->FindI("pkgProblemResolver::Scores::Required",2), + _config->FindI("pkgProblemResolver::Scores::Important",2), + _config->FindI("pkgProblemResolver::Scores::Required",3), _config->FindI("pkgProblemResolver::Scores::Standard",1), _config->FindI("pkgProblemResolver::Scores::Optional",-1), _config->FindI("pkgProblemResolver::Scores::Extra",-2) @@ -568,11 +571,11 @@ void pkgProblemResolver::MakeScores() if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true) clog << "Settings used to calculate pkgProblemResolver::Scores::" << endl - << " Important => " << PrioMap[1] << endl - << " Required => " << PrioMap[2] << endl - << " Standard => " << PrioMap[3] << endl - << " Optional => " << PrioMap[4] << endl - << " Extra => " << PrioMap[5] << endl + << " Required => " << PrioMap[pkgCache::State::Required] << endl + << " Important => " << PrioMap[pkgCache::State::Important] << endl + << " Standard => " << PrioMap[pkgCache::State::Standard] << endl + << " Optional => " << PrioMap[pkgCache::State::Optional] << endl + << " Extra => " << PrioMap[pkgCache::State::Extra] << endl << " Essentials => " << PrioEssentials << endl << " InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete << endl << " Depends => " << PrioDepends << endl diff --git a/apt-pkg/aptconfiguration.cc b/apt-pkg/aptconfiguration.cc index 653775688..37c846582 100644 --- a/apt-pkg/aptconfiguration.cc +++ b/apt-pkg/aptconfiguration.cc @@ -401,8 +401,8 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache close(external[1]); FILE *dpkg = fdopen(external[0], "r"); - char buf[1024]; if(dpkg != NULL) { + char buf[1024]; while (fgets(buf, sizeof(buf), dpkg) != NULL) { char* arch = strtok(buf, " "); while (arch != NULL) { diff --git a/apt-pkg/cachefilter.cc b/apt-pkg/cachefilter.cc index 58cc812bf..64cde41d1 100644 --- a/apt-pkg/cachefilter.cc +++ b/apt-pkg/cachefilter.cc @@ -71,8 +71,7 @@ static std::string CompleteArch(std::string const &arch) { } /*}}}*/ PackageArchitectureMatchesSpecification::PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern) :/*{{{*/ - literal(pattern), isPattern(isPattern), d(NULL) { - complete = CompleteArch(pattern); + literal(pattern), complete(CompleteArch(pattern)), isPattern(isPattern), d(NULL) { } /*}}}*/ bool PackageArchitectureMatchesSpecification::operator() (char const * const &arch) {/*{{{*/ diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index dcd353119..179a0e963 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -286,6 +286,8 @@ class pkgCache::DepIterator : public Iterator<Dependency, DepIterator> { bool IsIgnorable(PrvIterator const &Prv) const; bool IsIgnorable(PkgIterator const &Pkg) const; bool IsMultiArchImplicit() const; + bool IsSatisfied(VerIterator const &Ver) const; + bool IsSatisfied(PrvIterator const &Prv) const; void GlobOr(DepIterator &Start,DepIterator &End); Version **AllTargets() const; bool SmartTargetPkg(PkgIterator &Result) const; diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 4de17e3e1..808a708a1 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -958,7 +958,7 @@ Configuration::MatchAgainstConfig::MatchAgainstConfig(char const * Config) continue; } } - if (strings.size() == 0) + if (strings.empty() == true) patterns.push_back(NULL); } /*}}}*/ diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 4c224337e..c426293a3 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -387,7 +387,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c std::vector<string> List; - if (DirectoryExists(Dir.c_str()) == false) + if (DirectoryExists(Dir) == false) { _error->Error(_("List of files can't be created as '%s' is not a directory"), Dir.c_str()); return List; @@ -413,14 +413,14 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c if (Ent->d_type != DT_REG) #endif { - if (RealFileExists(File.c_str()) == false) + if (RealFileExists(File) == false) { // do not show ignoration warnings for directories if ( #ifdef _DIRENT_HAVE_D_TYPE Ent->d_type == DT_DIR || #endif - DirectoryExists(File.c_str()) == true) + DirectoryExists(File) == true) continue; if (SilentIgnore.Match(Ent->d_name) == false) _error->Notice(_("Ignoring '%s' in directory '%s' as it is not a regular file"), Ent->d_name, Dir.c_str()); @@ -501,7 +501,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, bool SortList) std::vector<string> List; - if (DirectoryExists(Dir.c_str()) == false) + if (DirectoryExists(Dir) == false) { _error->Error(_("List of files can't be created as '%s' is not a directory"), Dir.c_str()); return List; @@ -526,7 +526,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, bool SortList) if (Ent->d_type != DT_REG) #endif { - if (RealFileExists(File.c_str()) == false) + if (RealFileExists(File) == false) { if (Debug == true) std::clog << "Bad file: " << Ent->d_name << " → it is not a real file" << std::endl; diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc new file mode 100644 index 000000000..31db7d5fe --- /dev/null +++ b/apt-pkg/contrib/gpgv.cc @@ -0,0 +1,385 @@ +// -*- mode: cpp; mode: fold -*- +// Include Files /*{{{*/ +#include<config.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include<apt-pkg/configuration.h> +#include<apt-pkg/error.h> +#include<apt-pkg/strutl.h> +#include<apt-pkg/fileutl.h> +#include<apt-pkg/gpgv.h> + +#include <apti18n.h> + /*}}}*/ +static char * GenerateTemporaryFileTemplate(const char *basename) /*{{{*/ +{ + const char *tmpdir = getenv("TMPDIR"); +#ifdef P_tmpdir + if (!tmpdir) + tmpdir = P_tmpdir; +#endif + if (!tmpdir) + tmpdir = "/tmp"; + + std::string out; + strprintf(out, "%s/%s.XXXXXX", tmpdir, basename); + return strdup(out.c_str()); +} + /*}}}*/ +// ExecGPGV - returns the command needed for verify /*{{{*/ +// --------------------------------------------------------------------- +/* Generating the commandline for calling gpgv is somehow complicated as + we need to add multiple keyrings and user supplied options. + Also, as gpgv has no options to enforce a certain reduced style of + clear-signed files (=the complete content of the file is signed and + the content isn't encoded) we do a divide and conquer approach here + and split up the clear-signed file in message and signature for gpgv +*/ +void ExecGPGV(std::string const &File, std::string const &FileGPG, + int const &statusfd, int fd[2]) +{ + #define EINTERNAL 111 + std::string const gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv"); + // FIXME: remove support for deprecated APT::GPGV setting + std::string const trustedFile = _config->Find("APT::GPGV::TrustedKeyring", _config->FindFile("Dir::Etc::Trusted")); + std::string const trustedPath = _config->FindDir("Dir::Etc::TrustedParts"); + + bool const Debug = _config->FindB("Debug::Acquire::gpgv", false); + + if (Debug == true) + { + std::clog << "gpgv path: " << gpgvpath << std::endl; + std::clog << "Keyring file: " << trustedFile << std::endl; + std::clog << "Keyring path: " << trustedPath << std::endl; + } + + std::vector<std::string> keyrings; + if (DirectoryExists(trustedPath)) + keyrings = GetListOfFilesInDir(trustedPath, "gpg", false, true); + if (RealFileExists(trustedFile) == true) + keyrings.push_back(trustedFile); + + std::vector<const char *> Args; + Args.reserve(30); + + if (keyrings.empty() == true) + { + // TRANSLATOR: %s is the trusted keyring parts directory + ioprintf(std::cerr, _("No keyring installed in %s."), + _config->FindDir("Dir::Etc::TrustedParts").c_str()); + exit(EINTERNAL); + } + + Args.push_back(gpgvpath.c_str()); + Args.push_back("--ignore-time-conflict"); + + char statusfdstr[10]; + if (statusfd != -1) + { + Args.push_back("--status-fd"); + snprintf(statusfdstr, sizeof(statusfdstr), "%i", statusfd); + Args.push_back(statusfdstr); + } + + for (std::vector<std::string>::const_iterator K = keyrings.begin(); + K != keyrings.end(); ++K) + { + Args.push_back("--keyring"); + Args.push_back(K->c_str()); + } + + Configuration::Item const *Opts; + Opts = _config->Tree("Acquire::gpgv::Options"); + if (Opts != 0) + { + Opts = Opts->Child; + for (; Opts != 0; Opts = Opts->Next) + { + if (Opts->Value.empty() == true) + continue; + Args.push_back(Opts->Value.c_str()); + } + } + + std::vector<std::string> dataHeader; + char * sig = NULL; + char * data = NULL; + + // file with detached signature + if (FileGPG != File) + { + Args.push_back(FileGPG.c_str()); + Args.push_back(File.c_str()); + } + else // clear-signed file + { + sig = GenerateTemporaryFileTemplate("apt.sig"); + data = GenerateTemporaryFileTemplate("apt.data"); + if (sig == NULL || data == NULL) + { + ioprintf(std::cerr, "Couldn't create tempfile names for splitting up %s", File.c_str()); + exit(EINTERNAL); + } + + int const sigFd = mkstemp(sig); + int const dataFd = mkstemp(data); + if (sigFd == -1 || dataFd == -1) + { + if (dataFd != -1) + unlink(sig); + if (sigFd != -1) + unlink(data); + ioprintf(std::cerr, "Couldn't create tempfiles for splitting up %s", File.c_str()); + exit(EINTERNAL); + } + + FileFd signature; + signature.OpenDescriptor(sigFd, FileFd::WriteOnly, true); + FileFd message; + message.OpenDescriptor(dataFd, FileFd::WriteOnly, true); + + if (signature.Failed() == true || message.Failed() == true || + SplitClearSignedFile(File, &message, &dataHeader, &signature) == false) + { + if (dataFd != -1) + unlink(sig); + if (sigFd != -1) + unlink(data); + ioprintf(std::cerr, "Splitting up %s into data and signature failed", File.c_str()); + exit(EINTERNAL); + } + Args.push_back(sig); + Args.push_back(data); + } + + Args.push_back(NULL); + + if (Debug == true) + { + std::clog << "Preparing to exec: " << gpgvpath; + for (std::vector<const char *>::const_iterator a = Args.begin(); *a != NULL; ++a) + std::clog << " " << *a; + std::clog << std::endl; + } + + if (statusfd != -1) + { + int const nullfd = open("/dev/null", O_RDONLY); + close(fd[0]); + // Redirect output to /dev/null; we read from the status fd + if (statusfd != STDOUT_FILENO) + dup2(nullfd, STDOUT_FILENO); + if (statusfd != STDERR_FILENO) + dup2(nullfd, STDERR_FILENO); + // Redirect the pipe to the status fd (3) + dup2(fd[1], statusfd); + + putenv((char *)"LANG="); + putenv((char *)"LC_ALL="); + putenv((char *)"LC_MESSAGES="); + } + + if (FileGPG != File) + { + execvp(gpgvpath.c_str(), (char **) &Args[0]); + ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str()); + exit(EINTERNAL); + } + else + { +//#define UNLINK_EXIT(X) exit(X) +#define UNLINK_EXIT(X) unlink(sig);unlink(data);exit(X) + + // for clear-signed files we have created tempfiles we have to clean up + // and we do an additional check, so fork yet another time … + pid_t pid = ExecFork(); + if(pid < 0) { + ioprintf(std::cerr, "Fork failed for %s to check %s", Args[0], File.c_str()); + UNLINK_EXIT(EINTERNAL); + } + if(pid == 0) + { + if (statusfd != -1) + dup2(fd[1], statusfd); + execvp(gpgvpath.c_str(), (char **) &Args[0]); + ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str()); + UNLINK_EXIT(EINTERNAL); + } + + // Wait and collect the error code - taken from WaitPid as we need the exact Status + int Status; + while (waitpid(pid,&Status,0) != pid) + { + if (errno == EINTR) + continue; + ioprintf(std::cerr, _("Waited for %s but it wasn't there"), "gpgv"); + UNLINK_EXIT(EINTERNAL); + } +#undef UNLINK_EXIT + // we don't need the files any longer + unlink(sig); + unlink(data); + free(sig); + free(data); + + // check if it exit'ed normally … + if (WIFEXITED(Status) == false) + { + ioprintf(std::cerr, _("Sub-process %s exited unexpectedly"), "gpgv"); + exit(EINTERNAL); + } + + // … and with a good exit code + if (WEXITSTATUS(Status) != 0) + { + ioprintf(std::cerr, _("Sub-process %s returned an error code (%u)"), "gpgv", WEXITSTATUS(Status)); + exit(WEXITSTATUS(Status)); + } + + // everything fine + exit(0); + } + exit(EINTERNAL); // unreachable safe-guard +} + /*}}}*/ +// SplitClearSignedFile - split message into data/signature /*{{{*/ +bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, + std::vector<std::string> * const ContentHeader, FileFd * const SignatureFile) +{ + FILE *in = fopen(InFile.c_str(), "r"); + if (in == NULL) + return _error->Errno("fopen", "can not open %s", InFile.c_str()); + + bool found_message_start = false; + bool found_message_end = false; + bool skip_until_empty_line = false; + bool found_signature = false; + bool first_line = true; + + char *buf = NULL; + size_t buf_size = 0; + ssize_t line_len = 0; + while ((line_len = getline(&buf, &buf_size, in)) != -1) + { + _strrstrip(buf); + if (found_message_start == false) + { + if (strcmp(buf, "-----BEGIN PGP SIGNED MESSAGE-----") == 0) + { + found_message_start = true; + skip_until_empty_line = true; + } + } + else if (skip_until_empty_line == true) + { + if (strlen(buf) == 0) + skip_until_empty_line = false; + // save "Hash" Armor Headers, others aren't allowed + else if (ContentHeader != NULL && strncmp(buf, "Hash: ", strlen("Hash: ")) == 0) + ContentHeader->push_back(buf); + } + else if (found_signature == false) + { + if (strcmp(buf, "-----BEGIN PGP SIGNATURE-----") == 0) + { + found_signature = true; + found_message_end = true; + if (SignatureFile != NULL) + { + SignatureFile->Write(buf, strlen(buf)); + SignatureFile->Write("\n", 1); + } + } + else if (found_message_end == false) // we are in the message block + { + // we don't have any fields which need dash-escaped, + // but implementations are free to encode all lines … + char const * dashfree = buf; + if (strncmp(dashfree, "- ", 2) == 0) + dashfree += 2; + if(first_line == true) // first line does not need a newline + first_line = false; + else if (ContentFile != NULL) + ContentFile->Write("\n", 1); + else + continue; + if (ContentFile != NULL) + ContentFile->Write(dashfree, strlen(dashfree)); + } + } + else if (found_signature == true) + { + if (SignatureFile != NULL) + { + SignatureFile->Write(buf, strlen(buf)); + SignatureFile->Write("\n", 1); + } + if (strcmp(buf, "-----END PGP SIGNATURE-----") == 0) + found_signature = false; // look for other signatures + } + // all the rest is whitespace, unsigned garbage or additional message blocks we ignore + } + fclose(in); + + if (found_signature == true) + return _error->Error("Signature in file %s wasn't closed", InFile.c_str()); + + // if we haven't found any of them, this an unsigned file, + // so don't generate an error, but splitting was unsuccessful none-the-less + if (first_line == true && found_message_start == false && found_message_end == false) + return false; + // otherwise one missing indicates a syntax error + else if (first_line == true || found_message_start == false || found_message_end == false) + return _error->Error("Splitting of file %s failed as it doesn't contain all expected parts %i %i %i", InFile.c_str(), first_line, found_message_start, found_message_end); + + return true; +} + /*}}}*/ +bool OpenMaybeClearSignedFile(std::string const &ClearSignedFileName, FileFd &MessageFile) /*{{{*/ +{ + char * const message = GenerateTemporaryFileTemplate("fileutl.message"); + int const messageFd = mkstemp(message); + if (messageFd == -1) + { + free(message); + return _error->Errno("mkstemp", "Couldn't create temporary file to work with %s", ClearSignedFileName.c_str()); + } + // we have the fd, thats enough for us + unlink(message); + free(message); + + MessageFile.OpenDescriptor(messageFd, FileFd::ReadWrite, true); + if (MessageFile.Failed() == true) + return _error->Error("Couldn't open temporary file to work with %s", ClearSignedFileName.c_str()); + + _error->PushToStack(); + bool const splitDone = SplitClearSignedFile(ClearSignedFileName.c_str(), &MessageFile, NULL, NULL); + bool const errorDone = _error->PendingError(); + _error->MergeWithStack(); + if (splitDone == false) + { + MessageFile.Close(); + + if (errorDone == true) + return false; + + // we deal with an unsigned file + MessageFile.Open(ClearSignedFileName, FileFd::ReadOnly); + } + else // clear-signed + { + if (MessageFile.Seek(0) == false) + return _error->Errno("lseek", "Unable to seek back in message for file %s", ClearSignedFileName.c_str()); + } + + return MessageFile.Failed() == false; +} + /*}}}*/ diff --git a/apt-pkg/contrib/gpgv.h b/apt-pkg/contrib/gpgv.h new file mode 100644 index 000000000..08b10a97a --- /dev/null +++ b/apt-pkg/contrib/gpgv.h @@ -0,0 +1,82 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Helpers to deal with gpgv better and more easily + + ##################################################################### */ + /*}}}*/ +#ifndef CONTRIB_GPGV_H +#define CONTRIB_GPGV_H + +#include <string> +#include <vector> + +#include <apt-pkg/fileutl.h> + +#if __GNUC__ >= 4 + #define APT_noreturn __attribute__ ((noreturn)) +#else + #define APT_noreturn /* no support */ +#endif + +/** \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). + * + * @param File is the message (unsigned or clear-signed) + * @param FileSig is the signature (detached or clear-signed) + */ +void ExecGPGV(std::string const &File, std::string const &FileSig, + int const &statusfd, int fd[2]) APT_noreturn; +inline void ExecGPGV(std::string const &File, std::string const &FileSig, + int const &statusfd = -1) { + int fd[2]; + ExecGPGV(File, FileSig, statusfd, fd); +}; + +#undef APT_noreturn + +/** \brief Split an inline signature into message and signature + * + * Takes a clear-signed message and puts the first signed message + * in the content file and all signatures following it into the + * second. Unsigned messages, additional messages as well as + * whitespaces are discarded. The resulting files are suitable to + * be checked with gpgv. + * + * If a FileFd pointers is NULL it will not be used and the content + * which would have been written to it is silently discarded. + * + * The content of the split files is undefined if the splitting was + * unsuccessful. + * + * Note that trying to split an unsigned file will fail, but + * not generate an error message. + * + * @param InFile is the clear-signed file + * @param ContentFile is the FileFd the message will be written to + * @param ContentHeader is a list of all required Amored Headers for the message + * @param SignatureFile is the FileFd all signatures will be written to + * @return true if the splitting was successful, false otherwise + */ +bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, + std::vector<std::string> * const ContentHeader, FileFd * const SignatureFile); + +/** \brief open a file which might be clear-signed + * + * This method tries to extract the (signed) message of a file. + * If the file isn't signed it will just open the given filename. + * Otherwise the message is extracted to a temporary file which + * will be opened instead. + * + * @param ClearSignedFileName is the name of the file to open + * @param[out] MessageFile is the FileFd in which the file will be opened + * @return true if opening was successful, otherwise false + */ +bool OpenMaybeClearSignedFile(std::string const &ClearSignedFileName, FileFd &MessageFile); + +#endif diff --git a/apt-pkg/contrib/netrc.cc b/apt-pkg/contrib/netrc.cc index 0a902f126..de95aa4ab 100644 --- a/apt-pkg/contrib/netrc.cc +++ b/apt-pkg/contrib/netrc.cc @@ -50,14 +50,10 @@ static int parsenetrc_string (char *host, std::string &login, std::string &passw FILE *file; int retcode = 1; int specific_login = (login.empty() == false); - char *home = NULL; bool netrc_alloc = false; - int state_our_login = false; /* With specific_login, - found *our* login name */ - if (!netrcfile) { - home = getenv ("HOME"); /* portable environment reader */ + char const * home = getenv ("HOME"); /* portable environment reader */ if (!home) { struct passwd *pw; @@ -86,6 +82,8 @@ static int parsenetrc_string (char *host, std::string &login, std::string &passw int state = NOTHING; char state_login = 0; /* Found a login keyword */ char state_password = 0; /* Found a password keyword */ + int state_our_login = false; /* With specific_login, + found *our* login name */ while (!done && getline(&netrcbuffer, &netrcbuffer_size, file) != -1) { tok = strtok_r (netrcbuffer, " \t\n", &tok_buf); diff --git a/apt-pkg/contrib/progress.cc b/apt-pkg/contrib/progress.cc index 317048845..916e1d730 100644 --- a/apt-pkg/contrib/progress.cc +++ b/apt-pkg/contrib/progress.cc @@ -176,7 +176,7 @@ void OpTextProgress::Update() if (OldOp.empty() == false) cout << endl; OldOp = "a"; - cout << Op << "..." << flush; + cout << Op << _("...") << flush; } return; @@ -192,7 +192,7 @@ void OpTextProgress::Update() } // Print the spinner - snprintf(S,sizeof(S),"\r%s... %u%%",Op.c_str(),(unsigned int)Percent); + snprintf(S,sizeof(S),_("%c%s... %u%%"),'\r',Op.c_str(),(unsigned int)Percent); Write(S); OldOp = Op; diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index df11a80ad..64731b482 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -117,7 +117,13 @@ char *_strstrip(char *String) if (*String == 0) return String; - + return _strrstrip(String); +} + /*}}}*/ +// strrstrip - Remove white space from the back of a string /*{{{*/ +// --------------------------------------------------------------------- +char *_strrstrip(char *String) +{ char *End = String + strlen(String) - 1; for (;End != String - 1 && (*End == ' ' || *End == '\t' || *End == '\n' || *End == '\r'); End--); @@ -1247,7 +1253,7 @@ string StripEpoch(const string &VerStr) return VerStr; return VerStr.substr(i+1); } - + /*}}}*/ // tolower_ascii - tolower() function that ignores the locale /*{{{*/ // --------------------------------------------------------------------- /* This little function is the most called method we have and tries @@ -1285,14 +1291,14 @@ bool CheckDomainList(const string &Host,const string &List) return false; } /*}}}*/ -// DeEscapeString - unescape (\0XX and \xXX) from a string /*{{{*/ +// DeEscapeString - unescape (\0XX and \xXX) from a string /*{{{*/ // --------------------------------------------------------------------- /* */ string DeEscapeString(const string &input) { char tmp[3]; - string::const_iterator it, escape_start; - string output, octal, hex; + string::const_iterator it; + string output; for (it = input.begin(); it != input.end(); ++it) { // just copy non-escape chars diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index 337139d5d..e92f91dc0 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -35,6 +35,7 @@ using std::ostream; bool UTF8ToCodeset(const char *codeset, const std::string &orig, std::string *dest); char *_strstrip(char *String); +char *_strrstrip(char *String); // right strip only char *_strtabexpand(char *String,size_t Len); bool ParseQuoteWord(const char *&String,std::string &Res); bool ParseCWord(const char *&String,std::string &Res); diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index de645bb6e..909dfcf47 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -22,6 +22,7 @@ #include <apt-pkg/strutl.h> #include <apt-pkg/acquire-item.h> #include <apt-pkg/debmetaindex.h> +#include <apt-pkg/gpgv.h> #include <sys/stat.h> /*}}}*/ @@ -337,7 +338,12 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (releaseExists == true || FileExists(ReleaseFile) == true) { - FileFd Rel(ReleaseFile,FileFd::ReadOnly); + FileFd Rel; + // Beware: The 'Release' file might be clearsigned in case the + // signature for an 'InRelease' file couldn't be checked + if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false) + return false; + if (_error->PendingError() == true) return false; Parser.LoadReleaseInfo(File,Rel,Section); diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index b84bd6fdd..db86bd698 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -28,12 +28,13 @@ using std::string; -static debListParser::WordList PrioList[] = {{"important",pkgCache::State::Important}, - {"required",pkgCache::State::Required}, - {"standard",pkgCache::State::Standard}, - {"optional",pkgCache::State::Optional}, - {"extra",pkgCache::State::Extra}, - {}}; +static debListParser::WordList PrioList[] = { + {"required",pkgCache::State::Required}, + {"important",pkgCache::State::Important}, + {"standard",pkgCache::State::Standard}, + {"optional",pkgCache::State::Optional}, + {"extra",pkgCache::State::Extra}, + {}}; // ListParser::debListParser - Constructor /*{{{*/ // --------------------------------------------------------------------- @@ -283,7 +284,7 @@ unsigned short debListParser::VersionHash() "Replaces",0}; unsigned long Result = INIT_FCS; char S[1024]; - for (const char **I = Sections; *I != 0; I++) + for (const char * const *I = Sections; *I != 0; ++I) { const char *Start; const char *End; @@ -294,13 +295,13 @@ unsigned short debListParser::VersionHash() of certain fields. dpkg also has the rather interesting notion of reformatting depends operators < -> <= */ char *J = S; - for (; Start != End; Start++) + for (; Start != End; ++Start) { - if (isspace(*Start) == 0) - *J++ = tolower_ascii(*Start); - if (*Start == '<' && Start[1] != '<' && Start[1] != '=') - *J++ = '='; - if (*Start == '>' && Start[1] != '>' && Start[1] != '=') + if (isspace(*Start) != 0) + continue; + *J++ = tolower_ascii(*Start); + + if ((*Start == '<' || *Start == '>') && Start[1] != *Start && Start[1] != '=') *J++ = '='; } @@ -800,13 +801,12 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI, map_ptrloc const storage = WriteUniqString(component); FileI->Component = storage; - // FIXME: Code depends on the fact that Release files aren't compressed + // FIXME: should use FileFd and TagSection FILE* release = fdopen(dup(File.Fd()), "r"); if (release == NULL) return false; char buffer[101]; - bool gpgClose = false; while (fgets(buffer, sizeof(buffer), release) != NULL) { size_t len = 0; @@ -818,15 +818,6 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI, if (buffer[len] == '\0') continue; - // only evalute the first GPG section - if (strncmp("-----", buffer, 5) == 0) - { - if (gpgClose == true) - break; - gpgClose = true; - continue; - } - // seperate the tag from the data const char* dataStart = strchr(buffer + len, ':'); if (dataStart == NULL) diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 6c191fd95..7a88d71e3 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -229,6 +229,8 @@ vector <struct IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const { /*}}}*/ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const { + bool const tryInRelease = _config->FindB("Acquire::TryInRelease", true); + // special case for --print-uris if (GetAll) { vector <struct IndexTarget *> *targets = ComputeIndexTargets(); @@ -239,18 +241,27 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const // this is normally created in pkgAcqMetaSig, but if we run // in --print-uris mode, we add it here - new pkgAcqMetaIndex(Owner, MetaIndexURI("Release"), - MetaIndexInfo("Release"), "Release", - MetaIndexURI("Release.gpg"), - ComputeIndexTargets(), - new indexRecords (Dist)); + if (tryInRelease == false) + new pkgAcqMetaIndex(Owner, MetaIndexURI("Release"), + MetaIndexInfo("Release"), "Release", + MetaIndexURI("Release.gpg"), + ComputeIndexTargets(), + new indexRecords (Dist)); } - new pkgAcqMetaSig(Owner, MetaIndexURI("Release.gpg"), - MetaIndexInfo("Release.gpg"), "Release.gpg", - MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release", - ComputeIndexTargets(), - new indexRecords (Dist)); + if (tryInRelease == true) + new pkgAcqMetaClearSig(Owner, MetaIndexURI("InRelease"), + MetaIndexInfo("InRelease"), "InRelease", + MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release", + MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg", + ComputeIndexTargets(), + new indexRecords (Dist)); + else + new pkgAcqMetaSig(Owner, MetaIndexURI("Release.gpg"), + MetaIndexInfo("Release.gpg"), "Release.gpg", + MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release", + ComputeIndexTargets(), + new indexRecords (Dist)); return true; } diff --git a/apt-pkg/deb/debversion.cc b/apt-pkg/deb/debversion.cc index a02699a44..140561262 100644 --- a/apt-pkg/deb/debversion.cc +++ b/apt-pkg/deb/debversion.cc @@ -215,10 +215,15 @@ bool debVersioningSystem::CheckDep(const char *PkgVer, return true; if (PkgVer == 0 || PkgVer[0] == 0) return false; - + Op &= 0x0F; + + // fast track for (equal) strings [by location] which are by definition equal versions + if (PkgVer == DepVer) + return Op == pkgCache::Dep::Equals || Op == pkgCache::Dep::LessEq || Op == pkgCache::Dep::GreaterEq; + // Perform the actual comparision. - int Res = CmpVersion(PkgVer,DepVer); - switch (Op & 0x0F) + int const Res = CmpVersion(PkgVer, DepVer); + switch (Op) { case pkgCache::Dep::LessEq: if (Res <= 0) diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index b4fcf47b6..3dec4bb39 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -146,11 +146,11 @@ static pkgCache::VerIterator FindNowVersion(const pkgCache::PkgIterator &Pkg) { pkgCache::VerIterator Ver; - for (Ver = Pkg.VersionList(); Ver.end() == false; Ver++) + for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) { pkgCache::VerFileIterator Vf = Ver.FileList(); pkgCache::PkgFileIterator F = Vf.File(); - for (F = Vf.File(); F.end() == false; F++) + for (F = Vf.File(); F.end() == false; ++F) { if (F && F.Archive()) { @@ -1615,12 +1615,12 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) if (!logfile_name.empty()) { FILE *log = NULL; - char buf[1024]; fprintf(report, "DpkgTerminalLog:\n"); log = fopen(logfile_name.c_str(),"r"); if(log != NULL) { + char buf[1024]; while( fgets(buf, sizeof(buf), log) != NULL) fprintf(report, " %s", buf); fprintf(report, " \n"); @@ -1657,13 +1657,11 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) // attach dmesg log (to learn about segfaults) if (FileExists("/bin/dmesg")) { - FILE *log = NULL; - char buf[1024]; - fprintf(report, "Dmesg:\n"); - log = popen("/bin/dmesg","r"); + FILE *log = popen("/bin/dmesg","r"); if(log != NULL) { + char buf[1024]; while( fgets(buf, sizeof(buf), log) != NULL) fprintf(report, " %s", buf); pclose(log); @@ -1673,13 +1671,12 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) // attach df -l log (to learn about filesystem status) if (FileExists("/bin/df")) { - FILE *log = NULL; - char buf[1024]; fprintf(report, "Df:\n"); - log = popen("/bin/df -l","r"); + FILE *log = popen("/bin/df -l","r"); if(log != NULL) { + char buf[1024]; while( fgets(buf, sizeof(buf), log) != NULL) fprintf(report, " %s", buf); pclose(log); diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index a48cd8b0c..6a3e9bfc4 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -351,18 +351,15 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) PkgIterator Pkg = Dep.TargetPkg(); // Check the base package if (Type == NowVersion && Pkg->CurrentVer != 0) - if (VS().CheckDep(Pkg.CurrentVer().VerStr(),Dep->CompareOp, - Dep.TargetVer()) == true) + if (Dep.IsSatisfied(Pkg.CurrentVer()) == true) return true; if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0) - if (VS().CheckDep(PkgState[Pkg->ID].InstVerIter(*this).VerStr(), - Dep->CompareOp,Dep.TargetVer()) == true) + if (Dep.IsSatisfied(PkgState[Pkg->ID].InstVerIter(*this)) == true) return true; if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0) - if (VS().CheckDep(PkgState[Pkg->ID].CandidateVerIter(*this).VerStr(), - Dep->CompareOp,Dep.TargetVer()) == true) + if (Dep.IsSatisfied(PkgState[Pkg->ID].CandidateVerIter(*this)) == true) return true; } @@ -398,7 +395,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) } // Compare the versions. - if (VS().CheckDep(P.ProvideVersion(),Dep->CompareOp,Dep.TargetVer()) == true) + if (Dep.IsSatisfied(P) == true) { Res = P.OwnerPkg(); return true; @@ -1192,14 +1189,13 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, { APT::VersionList verlist; pkgCache::VerIterator Cand = PkgState[Start.TargetPkg()->ID].CandidateVerIter(*this); - if (Cand.end() == false && VS().CheckDep(Cand.VerStr(), Start->CompareOp, Start.TargetVer()) == true) + if (Cand.end() == false && Start.IsSatisfied(Cand) == true) verlist.insert(Cand); for (PrvIterator Prv = Start.TargetPkg().ProvidesList(); Prv.end() != true; ++Prv) { pkgCache::VerIterator V = Prv.OwnerVer(); pkgCache::VerIterator Cand = PkgState[Prv.OwnerPkg()->ID].CandidateVerIter(*this); - if (Cand.end() == true || V != Cand || - VS().CheckDep(Prv.ProvideVersion(), Start->CompareOp, Start.TargetVer()) == false) + if (Cand.end() == true || V != Cand || Start.IsSatisfied(Prv) == false) continue; verlist.insert(Cand); } @@ -1407,7 +1403,7 @@ bool pkgDepCache::SetCandidateRelease(pkgCache::VerIterator TargetVer, if (Cand.end() == true) continue; // check if the current candidate is enough for the versioned dependency - and installable? - if (VS().CheckDep(P.CandVersion(), Start->CompareOp, Start.TargetVer()) == true && + if (Start.IsSatisfied(Cand) == true && (VersionState(Cand.DependsList(), DepInstall, DepCandMin, DepCandPolicy) & DepCandMin) == DepCandMin) { itsFine = true; @@ -1441,7 +1437,7 @@ bool pkgDepCache::SetCandidateRelease(pkgCache::VerIterator TargetVer, V = Match.Find(D.TargetPkg()); // check if the version from this release could satisfy the dependency - if (V.end() == true || VS().CheckDep(V.VerStr(), D->CompareOp, D.TargetVer()) == false) + if (V.end() == true || D.IsSatisfied(V) == false) { if (stillOr == true) continue; @@ -1771,7 +1767,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, for(VerIterator V = d.TargetPkg().VersionList(); !V.end(); ++V) { - if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer())) + if(d.IsSatisfied(V)) { if(debug_autoremove) { @@ -1793,8 +1789,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg, for(PrvIterator prv=d.TargetPkg().ProvidesList(); !prv.end(); ++prv) { - if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, - d.TargetVer())) + if(d.IsSatisfied(prv)) { if(debug_autoremove) { diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 6ce9da784..e90598392 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -475,7 +475,6 @@ bool EDSP::WriteSolution(pkgDepCache &Cache, FILE* output) fprintf(output, "Autoremove: %d\n", Pkg.CurrentVer()->ID); if (Debug == true) fprintf(output, "Package: %s\nVersion: %s\n", Pkg.FullName().c_str(), Pkg.CurrentVer().VerStr()); - fprintf(stderr, "Autoremove: %s\nVersion: %s\n", Pkg.FullName().c_str(), Pkg.CurrentVer().VerStr()); } else continue; diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index c0a085316..a262ef789 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -141,7 +141,6 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List, File = OrigPath + ChopDirs(File,Chop); // See if the file exists - bool Mangled = false; if (NoStat == false || Hits < 10) { // Attempt to fix broken structure @@ -164,6 +163,7 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List, if (stat(string(CDROM + Prefix + File).c_str(),&Buf) != 0 || Buf.st_size == 0) { + bool Mangled = false; // Attempt to fix busted symlink support for one instance string OrigFile = File; string::size_type Start = File.find("binary-"); @@ -593,9 +593,9 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList, if(pid == 0) { if (useInRelease == true) - RunGPGV(inrelease, inrelease); + ExecGPGV(inrelease, inrelease); else - RunGPGV(release, releasegpg); + ExecGPGV(release, releasegpg); } if(!ExecWait(pid, "gpgv")) { @@ -642,120 +642,6 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList, return true; } /*}}}*/ -// SigVerify::RunGPGV - returns the command needed for verify /*{{{*/ -// --------------------------------------------------------------------- -/* Generating the commandline for calling gpgv is somehow complicated as - we need to add multiple keyrings and user supplied options. Also, as - the cdrom code currently can not use the gpgv method we have two places - these need to be done - so the place for this method is wrong but better - than code duplication… */ -bool SigVerify::RunGPGV(std::string const &File, std::string const &FileGPG, - int const &statusfd, int fd[2]) -{ - if (File == FileGPG) - { - FILE* gpg = fopen(File.c_str(), "r"); - if (gpg == NULL) - return _error->Errno("RunGPGV", _("Could not open file %s"), File.c_str()); - fclose(gpg); - if (!StartsWithGPGClearTextSignature(File)) - return _error->Error(_("File %s doesn't start with a clearsigned message"), File.c_str()); - } - - - string const gpgvpath = _config->Find("Dir::Bin::gpg", "/usr/bin/gpgv"); - // FIXME: remove support for deprecated APT::GPGV setting - string const trustedFile = _config->Find("APT::GPGV::TrustedKeyring", _config->FindFile("Dir::Etc::Trusted")); - string const trustedPath = _config->FindDir("Dir::Etc::TrustedParts"); - - bool const Debug = _config->FindB("Debug::Acquire::gpgv", false); - - if (Debug == true) - { - std::clog << "gpgv path: " << gpgvpath << std::endl; - std::clog << "Keyring file: " << trustedFile << std::endl; - std::clog << "Keyring path: " << trustedPath << std::endl; - } - - std::vector<string> keyrings; - if (DirectoryExists(trustedPath)) - keyrings = GetListOfFilesInDir(trustedPath, "gpg", false, true); - if (RealFileExists(trustedFile) == true) - keyrings.push_back(trustedFile); - - std::vector<const char *> Args; - Args.reserve(30); - - if (keyrings.empty() == true) - { - // TRANSLATOR: %s is the trusted keyring parts directory - return _error->Error(_("No keyring installed in %s."), - _config->FindDir("Dir::Etc::TrustedParts").c_str()); - } - - Args.push_back(gpgvpath.c_str()); - Args.push_back("--ignore-time-conflict"); - - if (statusfd != -1) - { - Args.push_back("--status-fd"); - char fd[10]; - snprintf(fd, sizeof(fd), "%i", statusfd); - Args.push_back(fd); - } - - for (vector<string>::const_iterator K = keyrings.begin(); - K != keyrings.end(); ++K) - { - Args.push_back("--keyring"); - Args.push_back(K->c_str()); - } - - Configuration::Item const *Opts; - Opts = _config->Tree("Acquire::gpgv::Options"); - if (Opts != 0) - { - Opts = Opts->Child; - for (; Opts != 0; Opts = Opts->Next) - { - if (Opts->Value.empty() == true) - continue; - Args.push_back(Opts->Value.c_str()); - } - } - - Args.push_back(FileGPG.c_str()); - if (FileGPG != File) - Args.push_back(File.c_str()); - Args.push_back(NULL); - - if (Debug == true) - { - std::clog << "Preparing to exec: " << gpgvpath; - for (std::vector<const char *>::const_iterator a = Args.begin(); *a != NULL; ++a) - std::clog << " " << *a; - std::clog << std::endl; - } - - if (statusfd != -1) - { - int const nullfd = open("/dev/null", O_RDONLY); - close(fd[0]); - // Redirect output to /dev/null; we read from the status fd - dup2(nullfd, STDOUT_FILENO); - dup2(nullfd, STDERR_FILENO); - // Redirect the pipe to the status fd (3) - dup2(fd[1], statusfd); - - putenv((char *)"LANG="); - putenv((char *)"LC_ALL="); - putenv((char *)"LC_MESSAGES="); - } - - execvp(gpgvpath.c_str(), (char **) &Args[0]); - return true; -} - /*}}}*/ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ vector<string> &List, pkgCdromStatus *log) { @@ -795,9 +681,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ unsigned int WrongSize = 0; unsigned int Packages = 0; for (vector<string>::iterator I = List.begin(); I != List.end(); ++I) - { - string OrigPath = string(*I,CDROM.length()); - + { // Open the package file FileFd Pkg(*I, FileFd::ReadOnly, FileFd::Auto); off_t const FileSize = Pkg.Size(); diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h index e3de1afd9..aa221158e 100644 --- a/apt-pkg/indexcopy.h +++ b/apt-pkg/indexcopy.h @@ -14,6 +14,9 @@ #include <string> #include <stdio.h> +#include <apt-pkg/gpgv.h> +#include <apt-pkg/macros.h> + #ifndef APT_8_CLEANER_HEADERS using std::string; using std::vector; @@ -96,13 +99,15 @@ class SigVerify /*{{{*/ bool CopyAndVerify(std::string CDROM,std::string Name,std::vector<std::string> &SigList, std::vector<std::string> PkgList,std::vector<std::string> SrcList); - /** \brief generates and run the command to verify a file with gpgv */ - static bool RunGPGV(std::string const &File, std::string const &FileOut, - int const &statusfd, int fd[2]); - inline static bool RunGPGV(std::string const &File, std::string const &FileOut, + __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; + }; + __deprecated static bool RunGPGV(std::string const &File, std::string const &FileOut, int const &statusfd = -1) { - int fd[2]; - return RunGPGV(File, FileOut, statusfd, fd); + ExecGPGV(File, FileOut, statusfd); + return false; }; }; /*}}}*/ diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index af2639beb..e37a78cfb 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -12,6 +12,7 @@ #include <apt-pkg/configuration.h> #include <apt-pkg/fileutl.h> #include <apt-pkg/hashes.h> +#include <apt-pkg/gpgv.h> #include <sys/stat.h> #include <clocale> @@ -57,7 +58,10 @@ bool indexRecords::Exists(string const &MetaKey) const bool indexRecords::Load(const string Filename) /*{{{*/ { - FileFd Fd(Filename, FileFd::ReadOnly); + FileFd Fd; + if (OpenMaybeClearSignedFile(Filename, Fd) == false) + return false; + pkgTagFile TagFile(&Fd, Fd.Size() + 256); // XXX if (_error->PendingError() == true) { @@ -173,7 +177,7 @@ bool indexRecords::parseSumData(const char *&Start, const char *End, /*{{{*/ Hash = ""; Size = 0; /* Skip over the first blank */ - while ((*Start == '\t' || *Start == ' ' || *Start == '\n') + while ((*Start == '\t' || *Start == ' ' || *Start == '\n' || *Start == '\r') && Start < End) Start++; if (Start >= End) @@ -215,7 +219,8 @@ bool indexRecords::parseSumData(const char *&Start, const char *End, /*{{{*/ EntryEnd = Start; /* Find the end of the third entry (the filename) */ - while ((*EntryEnd != '\t' && *EntryEnd != ' ' && *EntryEnd != '\n') + while ((*EntryEnd != '\t' && *EntryEnd != ' ' && + *EntryEnd != '\n' && *EntryEnd != '\r') && EntryEnd < End) EntryEnd++; diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 27d7ead24..59729faf5 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -27,15 +27,13 @@ APT_DOMAIN:=libapt-pkg$(LIBAPTPKG_MAJOR) SOURCE = contrib/mmap.cc contrib/error.cc contrib/strutl.cc \ contrib/configuration.cc contrib/progress.cc contrib/cmndline.cc \ contrib/hashsum.cc contrib/md5.cc contrib/sha1.cc \ - contrib/sha2_internal.cc\ - contrib/hashes.cc \ + contrib/sha2_internal.cc contrib/hashes.cc \ contrib/cdromutl.cc contrib/crc-16.cc contrib/netrc.cc \ - contrib/fileutl.cc -HEADERS = mmap.h error.h configuration.h fileutl.h cmndline.h netrc.h\ - md5.h crc-16.h cdromutl.h strutl.h sptr.h sha1.h sha2.h sha256.h\ - sha2_internal.h \ - hashes.h hashsum_template.h\ - macros.h weakptr.h + contrib/fileutl.cc contrib/gpgv.cc +HEADERS = mmap.h error.h configuration.h fileutl.h cmndline.h netrc.h \ + md5.h crc-16.h cdromutl.h strutl.h sptr.h sha1.h sha2.h sha256.h \ + sha2_internal.h hashes.h hashsum_template.h \ + macros.h weakptr.h gpgv.h # Source code for the core main library SOURCE+= pkgcache.cc version.cc depcache.cc \ diff --git a/apt-pkg/orderlist.cc b/apt-pkg/orderlist.cc index 3a179b2a2..80d8fd490 100644 --- a/apt-pkg/orderlist.cc +++ b/apt-pkg/orderlist.cc @@ -331,9 +331,11 @@ int pkgOrderList::Score(PkgIterator Pkg) } // Important Required Standard Optional Extra - signed short PrioMap[] = {0,5,4,3,1,0}; if (Cache[Pkg].InstVerIter(Cache)->Priority <= 5) + { + signed short PrioMap[] = {0,5,4,3,1,0}; Score += PrioMap[Cache[Pkg].InstVerIter(Cache)->Priority]; + } return Score; } /*}}}*/ diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 1de33ff9b..d7725563b 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -52,7 +52,7 @@ pkgCache::Header::Header() /* Whenever the structures change the major version should be bumped, whenever the generator changes the minor version should be bumped. */ MajorVersion = 8; - MinorVersion = 0; + MinorVersion = 1; Dirty = false; HeaderSz = sizeof(pkgCache::Header); @@ -182,18 +182,17 @@ unsigned long pkgCache::sHash(const string &Str) const { unsigned long Hash = 0; for (string::const_iterator I = Str.begin(); I != Str.end(); ++I) - Hash = 5*Hash + tolower_ascii(*I); + Hash = 41 * Hash + tolower_ascii(*I); return Hash % _count(HeaderP->PkgHashTable); } unsigned long pkgCache::sHash(const char *Str) const { - unsigned long Hash = 0; - for (const char *I = Str; *I != 0; ++I) - Hash = 5*Hash + tolower_ascii(*I); + unsigned long Hash = tolower_ascii(*Str); + for (const char *I = Str + 1; *I != 0; ++I) + Hash = 41 * Hash + tolower_ascii(*I); return Hash % _count(HeaderP->PkgHashTable); } - /*}}}*/ // Cache::SingleArchFindPkg - Locate a package by name /*{{{*/ // --------------------------------------------------------------------- @@ -206,9 +205,14 @@ pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name) Package *Pkg = PkgP + HeaderP->PkgHashTable[Hash(Name)]; for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage) { - if (Pkg->Name != 0 && StrP[Pkg->Name] == Name[0] && - stringcasecmp(Name,StrP + Pkg->Name) == 0) - return PkgIterator(*this,Pkg); + if (unlikely(Pkg->Name == 0)) + continue; + + int const cmp = strcasecmp(Name.c_str(), StrP + Pkg->Name); + if (cmp == 0) + return PkgIterator(*this, Pkg); + else if (cmp < 0) + break; } return PkgIterator(*this,0); } @@ -265,9 +269,14 @@ pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) { // Look at the hash bucket for the group Group *Grp = GrpP + HeaderP->GrpHashTable[sHash(Name)]; for (; Grp != GrpP; Grp = GrpP + Grp->Next) { - if (Grp->Name != 0 && StrP[Grp->Name] == Name[0] && - stringcasecmp(Name, StrP + Grp->Name) == 0) + if (unlikely(Grp->Name == 0)) + continue; + + int const cmp = strcasecmp(Name.c_str(), StrP + Grp->Name); + if (cmp == 0) return GrpIterator(*this, Grp); + else if (cmp < 0) + break; } return GrpIterator(*this,0); @@ -279,22 +288,22 @@ pkgCache::GrpIterator pkgCache::FindGrp(const string &Name) { type in the weird debian style.. */ const char *pkgCache::CompTypeDeb(unsigned char Comp) { - const char *Ops[] = {"","<=",">=","<<",">>","=","!="}; - if ((unsigned)(Comp & 0xF) < 7) - return Ops[Comp & 0xF]; - return ""; + const char * const Ops[] = {"","<=",">=","<<",">>","=","!="}; + if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0]))) + return ""; + return Ops[Comp & 0xF]; } /*}}}*/ // Cache::CompType - Return a string describing the compare type /*{{{*/ // --------------------------------------------------------------------- -/* This returns a string representation of the dependency compare +/* This returns a string representation of the dependency compare type */ const char *pkgCache::CompType(unsigned char Comp) { - const char *Ops[] = {"","<=",">=","<",">","=","!="}; - if ((unsigned)(Comp & 0xF) < 7) - return Ops[Comp & 0xF]; - return ""; + const char * const Ops[] = {"","<=",">=","<",">","=","!="}; + if (unlikely((unsigned)(Comp & 0xF) >= sizeof(Ops)/sizeof(Ops[0]))) + return ""; + return Ops[Comp & 0xF]; } /*}}}*/ // Cache::DepType - Return a string describing the dep type /*{{{*/ @@ -625,8 +634,7 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets() const { if (IsIgnorable(I.ParentPkg()) == true) continue; - - if (Owner->VS->CheckDep(I.VerStr(),S->CompareOp,TargetVer()) == false) + if (IsSatisfied(I) == false) continue; Size++; @@ -639,8 +647,7 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets() const { if (IsIgnorable(I) == true) continue; - - if (Owner->VS->CheckDep(I.ProvideVersion(),S->CompareOp,TargetVer()) == false) + if (IsSatisfied(I) == false) continue; Size++; @@ -748,6 +755,16 @@ bool pkgCache::DepIterator::IsMultiArchImplicit() const return false; } /*}}}*/ +// DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/ +bool pkgCache::DepIterator::IsSatisfied(VerIterator const &Ver) const +{ + return Owner->VS->CheckDep(Ver.VerStr(),S->CompareOp,TargetVer()); +} +bool pkgCache::DepIterator::IsSatisfied(PrvIterator const &Prv) const +{ + return Owner->VS->CheckDep(Prv.ProvideVersion(),S->CompareOp,TargetVer()); +} + /*}}}*/ // ostream operator to handle string representation of a dependecy /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 373f6625c..3f10b6c40 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -300,36 +300,35 @@ bool pkgCacheGenerator::MergeListPackage(ListParser &List, pkgCache::PkgIterator for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) { - pkgCache::DescIterator Desc = Ver.DescriptionList(); + pkgCache::DescIterator VerDesc = Ver.DescriptionList(); // a version can only have one md5 describing it - if (Desc.end() == true || MD5SumValue(Desc.md5()) != CurMd5) + if (VerDesc.end() == true || MD5SumValue(VerDesc.md5()) != CurMd5) continue; // don't add a new description if we have one for the given // md5 && language - if (IsDuplicateDescription(Desc, CurMd5, CurLang) == true) + if (IsDuplicateDescription(VerDesc, CurMd5, CurLang) == true) continue; + pkgCache::DescIterator Desc; Dynamic<pkgCache::DescIterator> DynDesc(Desc); - // we add at the end, so that the start is constant as we need - // that to be able to efficiently share these lists - map_ptrloc *LastDesc = &Ver->DescriptionList; - for (;Desc.end() == false && Desc->NextDesc != 0; ++Desc); - if (Desc.end() == false) - LastDesc = &Desc->NextDesc; - void const * const oldMap = Map.Data(); - map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, *LastDesc); + map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, VerDesc->md5sum); if (unlikely(descindex == 0 && _error->PendingError())) return _error->Error(_("Error occurred while processing %s (%s%d)"), Pkg.Name(), "NewDescription", 1); - if (oldMap != Map.Data()) - LastDesc += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; - *LastDesc = descindex; + Desc->ParentPkg = Pkg.Index(); - if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false) + // we add at the end, so that the start is constant as we need + // that to be able to efficiently share these lists + VerDesc = Ver.DescriptionList(); // old value might be invalid after ReMap + for (;VerDesc.end() == false && VerDesc->NextDesc != 0; ++VerDesc); + map_ptrloc * const LastNextDesc = (VerDesc.end() == true) ? &Ver->DescriptionList : &VerDesc->NextDesc; + *LastNextDesc = descindex; + + if (NewFileDesc(Desc,List) == false) return _error->Error(_("Error occurred while processing %s (%s%d)"), Pkg.Name(), "NewFileDesc", 1); @@ -391,7 +390,7 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator } // Add a new version - map_ptrloc const verindex = NewVersion(Ver,Version,*LastVer); + map_ptrloc const verindex = NewVersion(Ver, Version, Pkg.Index(), Hash, *LastVer); if (verindex == 0 && _error->PendingError()) return _error->Error(_("Error occurred while processing %s (%s%d)"), Pkg.Name(), "NewVersion", 1); @@ -399,8 +398,6 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator if (oldMap != Map.Data()) LastVer += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; *LastVer = verindex; - Ver->ParentPkg = Pkg.Index(); - Ver->Hash = Hash; if (unlikely(List.NewVersion(Ver) == false)) return _error->Error(_("Error occurred while processing %s (%s%d)"), @@ -464,11 +461,8 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator pkgCache::VerIterator ConVersion = D.ParentVer(); Dynamic<pkgCache::VerIterator> DynV(ConVersion); // duplicate the Conflicts/Breaks/Replaces for :none arch - if (D->Version == 0) - NewDepends(Pkg, ConVersion, "", 0, D->Type, OldDepLast); - else - NewDepends(Pkg, ConVersion, D.TargetVer(), - D->CompareOp, D->Type, OldDepLast); + NewDepends(Pkg, ConVersion, D->Version, + D->CompareOp, D->Type, OldDepLast); } } } @@ -509,19 +503,16 @@ bool pkgCacheGenerator::MergeListVersion(ListParser &List, pkgCache::PkgIterator // We haven't found reusable descriptions, so add the first description pkgCache::DescIterator Desc = Ver.DescriptionList(); Dynamic<pkgCache::DescIterator> DynDesc(Desc); - map_ptrloc *LastDesc = &Ver->DescriptionList; - oldMap = Map.Data(); - map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, *LastDesc); + map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, 0); if (unlikely(descindex == 0 && _error->PendingError())) return _error->Error(_("Error occurred while processing %s (%s%d)"), Pkg.Name(), "NewDescription", 2); - if (oldMap != Map.Data()) - LastDesc += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; - *LastDesc = descindex; + Desc->ParentPkg = Pkg.Index(); + Ver->DescriptionList = descindex; - if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false) + if (NewFileDesc(Desc,List) == false) return _error->Error(_("Error occurred while processing %s (%s%d)"), Pkg.Name(), "NewFileDesc", 2); @@ -564,7 +555,7 @@ bool pkgCacheGenerator::MergeFileProvides(ListParser &List) Dynamic<pkgCache::VerIterator> DynVer(Ver); for (; Ver.end() == false; ++Ver) { - if (Ver->Hash == Hash && Version.c_str() == Ver.VerStr()) + if (Ver->Hash == Hash && Version == Ver.VerStr()) { if (List.CollectFileProvides(Cache,Ver) == false) return _error->Error(_("Error occurred while processing %s (%s%d)"), @@ -602,8 +593,11 @@ bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name) // Insert it into the hash table unsigned long const Hash = Cache.Hash(Name); - Grp->Next = Cache.HeaderP->GrpHashTable[Hash]; - Cache.HeaderP->GrpHashTable[Hash] = Group; + map_ptrloc *insertAt = &Cache.HeaderP->GrpHashTable[Hash]; + while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + *insertAt)->Name) > 0) + insertAt = &(Cache.GrpP + *insertAt)->Next; + Grp->Next = *insertAt; + *insertAt = Group; Grp->ID = Cache.HeaderP->GroupCount++; return true; @@ -632,11 +626,14 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name // Insert the package into our package list if (Grp->FirstPackage == 0) // the group is new { + Grp->FirstPackage = Package; // Insert it into the hash table unsigned long const Hash = Cache.Hash(Name); - Pkg->NextPackage = Cache.HeaderP->PkgHashTable[Hash]; - Cache.HeaderP->PkgHashTable[Hash] = Package; - Grp->FirstPackage = Package; + map_ptrloc *insertAt = &Cache.HeaderP->PkgHashTable[Hash]; + while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.PkgP + *insertAt)->Name) > 0) + insertAt = &(Cache.PkgP + *insertAt)->NextPackage; + Pkg->NextPackage = *insertAt; + *insertAt = Package; } else // Group the Packages together { @@ -675,6 +672,7 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator &G, bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same); pkgCache::PkgIterator D = G.PackageList(); Dynamic<pkgCache::PkgIterator> DynD(D); + map_ptrloc const VerStrIdx = V->VerStr; for (; D.end() != true; D = G.NextPkg(D)) { if (Arch == D.Arch() || D->VersionList == 0) @@ -685,16 +683,16 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator &G, if (coInstall == true) { // Replaces: ${self}:other ( << ${binary:Version}) - NewDepends(D, V, V.VerStr(), + NewDepends(D, V, VerStrIdx, pkgCache::Dep::Less, pkgCache::Dep::Replaces, OldDepLast); // Breaks: ${self}:other (!= ${binary:Version}) - NewDepends(D, V, V.VerStr(), + NewDepends(D, V, VerStrIdx, pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks, OldDepLast); } else { // Conflicts: ${self}:other - NewDepends(D, V, "", + NewDepends(D, V, 0, pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts, OldDepLast); } @@ -711,17 +709,18 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::VerIterator &V, bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same); if (coInstall == true) { + map_ptrloc const VerStrIdx = V->VerStr; // Replaces: ${self}:other ( << ${binary:Version}) - NewDepends(D, V, V.VerStr(), + NewDepends(D, V, VerStrIdx, pkgCache::Dep::Less, pkgCache::Dep::Replaces, OldDepLast); // Breaks: ${self}:other (!= ${binary:Version}) - NewDepends(D, V, V.VerStr(), + NewDepends(D, V, VerStrIdx, pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks, OldDepLast); } else { // Conflicts: ${self}:other - NewDepends(D, V, "", + NewDepends(D, V, 0, pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts, OldDepLast); } @@ -767,6 +766,8 @@ bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver, /* This puts a version structure in the linked list */ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, const string &VerStr, + map_ptrloc const ParentPkg, + unsigned long const Hash, unsigned long Next) { // Get a structure @@ -778,12 +779,37 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version); //Dynamic<pkgCache::VerIterator> DynV(Ver); // caller MergeListVersion already takes care of it Ver->NextVer = Next; + Ver->ParentPkg = ParentPkg; + Ver->Hash = Hash; Ver->ID = Cache.HeaderP->VersionCount++; + + // try to find the version string in the group for reuse + pkgCache::PkgIterator Pkg = Ver.ParentPkg(); + pkgCache::GrpIterator Grp = Pkg.Group(); + if (Pkg.end() == false && Grp.end() == false) + { + for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P)) + { + if (Pkg == P) + continue; + for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V) + { + int const cmp = strcmp(V.VerStr(), VerStr.c_str()); + if (cmp == 0) + { + Ver->VerStr = V->VerStr; + return Version; + } + else if (cmp < 0) + break; + } + } + } + // haven't found the version string, so create map_ptrloc const idxVerStr = WriteStringInMap(VerStr); if (unlikely(idxVerStr == 0)) return 0; Ver->VerStr = idxVerStr; - return Version; } /*}}}*/ @@ -825,9 +851,9 @@ bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc, // --------------------------------------------------------------------- /* This puts a description structure in the linked list */ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, - const string &Lang, - const MD5SumValue &md5sum, - map_ptrloc Next) + const string &Lang, + const MD5SumValue &md5sum, + map_ptrloc idxmd5str) { // Get a structure map_ptrloc const Description = AllocateInMap(sizeof(pkgCache::Description)); @@ -836,14 +862,21 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, // Fill it in Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description); - Desc->NextDesc = Next; Desc->ID = Cache.HeaderP->DescriptionCount++; - map_ptrloc const idxlanguage_code = WriteStringInMap(Lang); - map_ptrloc const idxmd5sum = WriteStringInMap(md5sum.Value()); - if (unlikely(idxlanguage_code == 0 || idxmd5sum == 0)) + map_ptrloc const idxlanguage_code = WriteUniqString(Lang); + if (unlikely(idxlanguage_code == 0)) return 0; Desc->language_code = idxlanguage_code; - Desc->md5sum = idxmd5sum; + + if (idxmd5str != 0) + Desc->md5sum = idxmd5str; + else + { + map_ptrloc const idxmd5sum = WriteStringInMap(md5sum.Value()); + if (unlikely(idxmd5sum == 0)) + return 0; + Desc->md5sum = idxmd5sum; + } return Description; } @@ -859,34 +892,48 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, unsigned int const &Type, map_ptrloc* &OldDepLast) { + map_ptrloc index = 0; + if (Version.empty() == false) + { + int const CmpOp = Op & 0x0F; + // =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages) + if (CmpOp == pkgCache::Dep::Equals && strcmp(Version.c_str(), Ver.VerStr()) == 0) + index = Ver->VerStr; + + if (index == 0) + { + void const * const oldMap = Map.Data(); + index = WriteStringInMap(Version); + if (unlikely(index == 0)) + return false; + if (OldDepLast != 0 && oldMap != Map.Data()) + OldDepLast += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap; + } + } + return NewDepends(Pkg, Ver, index, Op, Type, OldDepLast); +} +bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, + pkgCache::VerIterator &Ver, + map_ptrloc const Version, + unsigned int const &Op, + unsigned int const &Type, + map_ptrloc* &OldDepLast) +{ void const * const oldMap = Map.Data(); // Get a structure map_ptrloc const Dependency = AllocateInMap(sizeof(pkgCache::Dependency)); if (unlikely(Dependency == 0)) return false; - + // Fill it in pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency); Dynamic<pkgCache::DepIterator> DynDep(Dep); Dep->ParentVer = Ver.Index(); Dep->Type = Type; Dep->CompareOp = Op; + Dep->Version = Version; Dep->ID = Cache.HeaderP->DependsCount++; - // Probe the reverse dependency list for a version string that matches - if (Version.empty() == false) - { -/* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++) - if (I->Version != 0 && I.TargetVer() == Version) - Dep->Version = I->Version;*/ - if (Dep->Version == 0) { - map_ptrloc const index = WriteStringInMap(Version); - if (unlikely(index == 0)) - return false; - Dep->Version = index; - } - } - // Link it to the package Dep->Package = Pkg.Index(); Dep->NextRevDepends = Pkg->RevDepends; diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index b6259b433..428e8459b 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -77,7 +77,14 @@ class pkgCacheGenerator /*{{{*/ bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, std::string const &Version, unsigned int const &Op, unsigned int const &Type, map_ptrloc* &OldDepLast); - unsigned long NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,unsigned long Next); + bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, + map_ptrloc const Version, unsigned int const &Op, + unsigned int const &Type, map_ptrloc* &OldDepLast); + __deprecated unsigned long NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,unsigned long Next) + { return NewVersion(Ver, VerStr, 0, 0, Next); } + unsigned long NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr, + map_ptrloc const ParentPkg, unsigned long const Hash, + unsigned long Next); map_ptrloc NewDescription(pkgCache::DescIterator &Desc,const std::string &Lang,const MD5SumValue &md5sum,map_ptrloc Next); public: diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 0fddfb451..0fd237cad 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -270,7 +270,11 @@ bool pkgSourceList::ReadAppend(string File) // CNC:2003-02-20 - Do not break if '#' is inside []. for (I = Buffer; *I != 0 && *I != '#'; I++) if (*I == '[') - I = strchr(I + 1, ']'); + { + char *b_end = strchr(I + 1, ']'); + if (b_end != NULL) + I = b_end; + } *I = 0; const char *C = _strstrip(Buffer); diff --git a/apt-pkg/srcrecords.cc b/apt-pkg/srcrecords.cc index d63d2c422..297559957 100644 --- a/apt-pkg/srcrecords.cc +++ b/apt-pkg/srcrecords.cc @@ -42,7 +42,7 @@ pkgSrcRecords::pkgSrcRecords(pkgSourceList &List) : d(NULL), Files(0), Current(0 } // Doesn't work without any source index files - if (Files.size() == 0) + if (Files.empty() == true) { _error->Error(_("You must put some 'source' URIs" " in your sources.list")); @@ -121,14 +121,13 @@ pkgSrcRecords::Parser *pkgSrcRecords::Find(const char *Package,bool const &SrcOn /* */ const char *pkgSrcRecords::Parser::BuildDepType(unsigned char const &Type) { - const char *fields[] = {"Build-Depends", - "Build-Depends-Indep", + const char *fields[] = {"Build-Depends", + "Build-Depends-Indep", "Build-Conflicts", "Build-Conflicts-Indep"}; - if (Type < 4) - return fields[Type]; - else + if (unlikely(Type >= sizeof(fields)/sizeof(fields[0]))) return ""; + return fields[Type]; } /*}}}*/ diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 79811899a..1c79ee74f 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -282,10 +282,17 @@ void pkgTagSection::Trim() for (; Stop > Section + 2 && (Stop[-2] == '\n' || Stop[-2] == '\r'); Stop--); } /*}}}*/ +// TagSection::Exists - return True if a tag exists /*{{{*/ +bool pkgTagSection::Exists(const char* const Tag) +{ + unsigned int tmp; + return Find(Tag, tmp); +} + /*}}}*/ // TagSection::Find - Locate a tag /*{{{*/ // --------------------------------------------------------------------- /* This searches the section for a tag that matches the given string. */ -bool pkgTagSection::Find(const char *Tag,unsigned &Pos) const +bool pkgTagSection::Find(const char *Tag,unsigned int &Pos) const { unsigned int Length = strlen(Tag); unsigned int I = AlphaIndexes[AlphaHash(Tag)]; diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index fd24471c1..4718f5101 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -59,7 +59,7 @@ class pkgTagSection inline bool operator !=(const pkgTagSection &rhs) {return Section != rhs.Section;}; bool Find(const char *Tag,const char *&Start, const char *&End) const; - bool Find(const char *Tag,unsigned &Pos) const; + bool Find(const char *Tag,unsigned int &Pos) const; std::string FindS(const char *Tag) const; signed int FindI(const char *Tag,signed long Default = 0) const ; unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const; @@ -73,7 +73,7 @@ class pkgTagSection virtual void TrimRecord(bool BeforeRecord, const char* &End); inline unsigned int Count() const {return TagCount;}; - inline bool Exists(const char* const Tag) {return AlphaIndexes[AlphaHash(Tag)] != 0;} + bool Exists(const char* const Tag); inline void Get(const char *&Start,const char *&Stop,unsigned int I) const {Start = Section + Indexes[I]; Stop = Section + Indexes[I+1];} diff --git a/apt-pkg/vendor.cc b/apt-pkg/vendor.cc index 36fc25957..fc03ec845 100644 --- a/apt-pkg/vendor.cc +++ b/apt-pkg/vendor.cc @@ -12,7 +12,7 @@ Vendor::Vendor(std::string VendorID, this->VendorID = VendorID; this->Origin = Origin; for (std::vector<struct Vendor::Fingerprint *>::iterator I = FingerprintList->begin(); - I != FingerprintList->end(); I++) + I != FingerprintList->end(); ++I) { if (_config->FindB("Debug::Vendor", false)) std::cerr << "Vendor \"" << VendorID << "\": Mapping \"" diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index e4fa0ea65..26262a010 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -181,9 +181,9 @@ pkgCache::VerIterator pkgVersionMatch::Find(pkgCache::PkgIterator Pkg) bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string) { if (pattern[0] == '/') { - bool res = false; size_t length = strlen(pattern); if (pattern[length - 1] == '/') { + bool res = false; regex_t preg; char *regex = strdup(pattern + 1); regex[length - 2] = '\0'; |