X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/acf09dfa0f6b654db3eae065ad73476d421ebfae..27f38567fe327ecaf7fb361c3cca6ee29e6300c9:/apt-pkg/deb/debsrcrecords.cc?ds=sidebyside diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc index 615f0f57d..5454d79c3 100644 --- a/apt-pkg/deb/debsrcrecords.cc +++ b/apt-pkg/deb/debsrcrecords.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,24 @@ using std::max; using std::string; +debSrcRecordParser::debSrcRecordParser(std::string const &File,pkgIndexFile const *Index) + : Parser(Index), d(NULL), Tags(&Fd), iOffset(0), Buffer(NULL) +{ + if (File.empty() == false) + { + if (Fd.Open(File, FileFd::ReadOnly, FileFd::Extension)) + Tags.Init(&Fd, 102400); + } +} +std::string debSrcRecordParser::Package() const /*{{{*/ +{ + auto const name = Sect.FindS("Package"); + if (iIndex == nullptr) + return name.empty() ? Sect.FindS("Source") : name; + else + return name; +} + /*}}}*/ // SrcRecordParser::Binaries - Return the binaries field /*{{{*/ // --------------------------------------------------------------------- /* This member parses the binaries field into a pair of class arrays and @@ -43,7 +62,7 @@ const char **debSrcRecordParser::Binaries() const char *Start, *End; if (Sect.Find("Binary", Start, End) == false) return NULL; - for (; isspace(*Start) != 0; ++Start); + for (; isspace_ascii(*Start) != 0; ++Start); if (Start >= End) return NULL; @@ -55,13 +74,14 @@ const char **debSrcRecordParser::Binaries() do { char* binStartNext = strchrnul(bin, ','); char* binEnd = binStartNext - 1; - for (; isspace(*binEnd) != 0; --binEnd) - binEnd = '\0'; + for (; isspace_ascii(*binEnd) != 0; --binEnd) + binEnd = 0; StaticBinList.push_back(bin); if (*binStartNext != ',') break; *binStartNext = '\0'; - for (bin = binStartNext + 1; isspace(*bin) != 0; ++bin); + for (bin = binStartNext + 1; isspace_ascii(*bin) != 0; ++bin) + ; } while (*bin != '\0'); StaticBinList.push_back(NULL); @@ -119,89 +139,137 @@ bool debSrcRecordParser::BuildDepends(std::vector &List) +bool debSrcRecordParser::Files(std::vector &F) { - List.erase(List.begin(),List.end()); - - // map from the Hashsum field to the hashsum function, - // unfortunately this is not a 1:1 mapping from - // Hashes::SupporedHashes as e.g. Files is a historic name for the md5 - const std::pair SourceHashFields[] = { - std::make_pair( "Checksums-Sha512", "SHA512"), - std::make_pair( "Checksums-Sha256", "SHA256"), - std::make_pair( "Checksums-Sha1", "SHA1"), - std::make_pair( "Files", "MD5Sum"), // historic Name - }; - - for (unsigned int i=0; - i < sizeof(SourceHashFields)/sizeof(SourceHashFields[0]); - i++) + std::vector F2; + if (Files2(F2) == false) + return false; + for (std::vector::const_iterator f2 = F2.begin(); f2 != F2.end(); ++f2) { - string Files = Sect.FindS(SourceHashFields[i].first); - if (Files.empty() == true) - continue; + pkgSrcRecords::File2 f; +#if __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + f.MD5Hash = f2->MD5Hash; + f.Size = f2->Size; +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif + f.Path = f2->Path; + f.Type = f2->Type; + F.push_back(f); + } + return true; +} +bool debSrcRecordParser::Files2(std::vector &List) +{ + List.clear(); - // Stash the / terminated directory prefix - string Base = Sect.FindS("Directory"); - if (Base.empty() == false && Base[Base.length()-1] != '/') - Base += '/'; + // Stash the / terminated directory prefix + string Base = Sect.FindS("Directory"); + if (Base.empty() == false && Base[Base.length()-1] != '/') + Base += '/'; - std::vector const compExts = APT::Configuration::getCompressorExtensions(); + std::vector const compExts = APT::Configuration::getCompressorExtensions(); + + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + { + // derive field from checksum type + std::string checksumField("Checksums-"); + if (strcmp(*type, "MD5Sum") == 0) + checksumField = "Files"; // historic name for MD5 checksums + else + checksumField.append(*type); + + string const Files = Sect.FindS(checksumField.c_str()); + if (Files.empty() == true) + continue; // Iterate over the entire list grabbing each triplet const char *C = Files.c_str(); while (*C != 0) - { - pkgSrcRecords::File F; - string Size; - - // Parse each of the elements - std::string RawHash; - if (ParseQuoteWord(C, RawHash) == false || - ParseQuoteWord(C, Size) == false || - ParseQuoteWord(C, F.Path) == false) - return _error->Error("Error parsing '%s' record", - SourceHashFields[i].first); - // assign full hash string - F.Hash = HashString(SourceHashFields[i].second, RawHash).toStr(); - // API compat hack - if(strcmp(SourceHashFields[i].second, "MD5Sum") == 0) - F.MD5Hash = RawHash; - - // Parse the size and append the directory - F.Size = atoi(Size.c_str()); - F.Path = Base + F.Path; - - // Try to guess what sort of file it is we are getting. - string::size_type Pos = F.Path.length()-1; - while (1) - { - string::size_type Tmp = F.Path.rfind('.',Pos); - if (Tmp == string::npos) - break; - if (F.Type == "tar") { - // source v3 has extension 'debian.tar.*' instead of 'diff.*' - if (string(F.Path, Tmp+1, Pos-Tmp) == "debian") - F.Type = "diff"; - break; - } - F.Type = string(F.Path,Tmp+1,Pos-Tmp); - - if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() || - F.Type == "tar") - { - Pos = Tmp-1; - continue; - } - - break; - } - - List.push_back(F); + { + string hash, size, path; + + // Parse each of the elements + if (ParseQuoteWord(C, hash) == false || + ParseQuoteWord(C, size) == false || + ParseQuoteWord(C, path) == false) + return _error->Error("Error parsing file record in %s of source package %s", checksumField.c_str(), Package().c_str()); + + if (iIndex == nullptr && checksumField == "Files") + { + // the Files field has a different format than the rest in deb-changes files + std::string ignore; + if (ParseQuoteWord(C, ignore) == false || + ParseQuoteWord(C, path) == false) + return _error->Error("Error parsing file record in %s of source package %s", checksumField.c_str(), Package().c_str()); + } + + HashString const hashString(*type, hash); + if (Base.empty() == false) + path = Base + path; + + // look if we have a record for this file already + std::vector::iterator file = List.begin(); + for (; file != List.end(); ++file) + if (file->Path == path) + break; + + // we have it already, store the new hash and be done + if (file != List.end()) + { + if (checksumField == "Files") + APT_IGNORE_DEPRECATED(file->MD5Hash = hash;) + // an error here indicates that we have two different hashes for the same file + if (file->Hashes.push_back(hashString) == false) + return _error->Error("Error parsing checksum in %s of source package %s", checksumField.c_str(), Package().c_str()); + continue; + } + + // we haven't seen this file yet + pkgSrcRecords::File2 F; + F.Path = path; + F.FileSize = strtoull(size.c_str(), NULL, 10); + F.Hashes.push_back(hashString); + F.Hashes.FileSize(F.FileSize); + + APT_IGNORE_DEPRECATED_PUSH + F.Size = F.FileSize; + if (checksumField == "Files") + F.MD5Hash = hash; + APT_IGNORE_DEPRECATED_POP + + // Try to guess what sort of file it is we are getting. + string::size_type Pos = F.Path.length()-1; + while (1) + { + string::size_type Tmp = F.Path.rfind('.',Pos); + if (Tmp == string::npos) + break; + if (F.Type == "tar") { + // source v3 has extension 'debian.tar.*' instead of 'diff.*' + if (string(F.Path, Tmp+1, Pos-Tmp) == "debian") + F.Type = "diff"; + break; + } + F.Type = string(F.Path,Tmp+1,Pos-Tmp); + + if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() || + F.Type == "tar") + { + Pos = Tmp-1; + continue; + } + + break; + } + List.push_back(F); } - break; } - return (List.size() > 0); + + return true; } /*}}}*/ // SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/ @@ -209,6 +277,25 @@ bool debSrcRecordParser::Files(std::vector &List) /* */ debSrcRecordParser::~debSrcRecordParser() { - delete[] Buffer; + // was allocated via strndup() + free(Buffer); } /*}}}*/ + + +debDscRecordParser::debDscRecordParser(std::string const &DscFile, pkgIndexFile const *Index) + : debSrcRecordParser("", Index) +{ + // support clear signed files + if (OpenMaybeClearSignedFile(DscFile, Fd) == false) + { + _error->Error("Failed to open %s", DscFile.c_str()); + return; + } + + // re-init to ensure the updated Fd is used + Tags.Init(&Fd, pkgTagFile::SUPPORT_COMMENTS); + // read the first (and only) record + Step(); + +}