X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/5abee4863220c2d9b135dc832b33c8680e5ba12e..eb0d90f08d6a6f2ee334a94f8fb45c776f5bcd6e:/ftparchive/writer.cc diff --git a/ftparchive/writer.cc b/ftparchive/writer.cc index 159772991..83c0b1e3f 100644 --- a/ftparchive/writer.cc +++ b/ftparchive/writer.cc @@ -13,26 +13,37 @@ // Include Files /*{{{*/ #include -#include -#include #include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include -#include -#include #include #include #include +#include +#include "apt-ftparchive.h" #include "writer.h" #include "cachedb.h" -#include "apt-ftparchive.h" #include "multicompress.h" #include @@ -43,14 +54,15 @@ FTWScanner *FTWScanner::Owner; // SetTFRewriteData - Helper for setting rewrite lists /*{{{*/ // --------------------------------------------------------------------- /* */ -inline void SetTFRewriteData(struct TFRewriteData &tfrd, - const char *tag, +static inline TFRewriteData SetTFRewriteData(const char *tag, const char *rewrite, const char *newtag = 0) { - tfrd.Tag = tag; - tfrd.Rewrite = rewrite; - tfrd.NewTag = newtag; + TFRewriteData tfrd; + tfrd.Tag = tag; + tfrd.Rewrite = rewrite; + tfrd.NewTag = newtag; + return tfrd; } /*}}}*/ @@ -70,9 +82,9 @@ FTWScanner::FTWScanner(string const &Arch): Arch(Arch) /*}}}*/ // FTWScanner::Scanner - FTW Scanner /*{{{*/ // --------------------------------------------------------------------- -/* This is the FTW scanner, it processes each directory element in the +/* This is the FTW scanner, it processes each directory element in the directory tree. */ -int FTWScanner::ScannerFTW(const char *File,const struct stat *sb,int Flag) +int FTWScanner::ScannerFTW(const char *File,const struct stat * /*sb*/,int Flag) { if (Flag == FTW_DNR) { @@ -282,7 +294,8 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath, if (link(FileName.c_str(),OriginalPath) != 0) { // Panic! Restore the symlink - symlink(OldLink,OriginalPath); + if (symlink(OldLink,OriginalPath) != 0) + _error->Errno("symlink", "failed to restore symlink"); return _error->Errno("link",_("*** Failed to link %s to %s"), FileName.c_str(), OriginalPath); @@ -318,7 +331,7 @@ PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string c DoMD5 = _config->FindB("APT::FTPArchive::Packages::MD5",DoMD5); DoSHA1 = _config->FindB("APT::FTPArchive::Packages::SHA1",DoSHA1); DoSHA256 = _config->FindB("APT::FTPArchive::Packages::SHA256",DoSHA256); - DoSHA256 = _config->FindB("APT::FTPArchive::Packages::SHA512",true); + DoSHA512 = _config->FindB("APT::FTPArchive::Packages::SHA512",DoSHA512); DoAlwaysStat = _config->FindB("APT::FTPArchive::AlwaysStat", false); DoContents = _config->FindB("APT::FTPArchive::Contents",true); NoOverride = _config->FindB("APT::FTPArchive::NoOverrideMsg",false); @@ -373,10 +386,14 @@ bool FTWScanner::SetExts(string const &Vals) bool PackagesWriter::DoPackage(string FileName) { // Pull all the data we need form the DB - if (Db.GetFileInfo(FileName, true, DoContents, true, DoMD5, DoSHA1, DoSHA256, DoSHA512, DoAlwaysStat) - == false) + if (Db.GetFileInfo(FileName, + true, /* DoControl */ + DoContents, + true, /* GenContentsOnly */ + false, /* DoSource */ + DoMD5, DoSHA1, DoSHA256, DoSHA512, DoAlwaysStat) == false) { - return false; + return false; } unsigned long long FileSize = Db.GetFileSize(); @@ -438,30 +455,28 @@ bool PackagesWriter::DoPackage(string FileName) } // This lists all the changes to the fields we are going to make. - // (7 hardcoded + maintainer + suggests + end marker) - TFRewriteData Changes[6+2+OverItem->FieldOverride.size()+1+1]; + std::vector Changes; - unsigned int End = 0; - SetTFRewriteData(Changes[End++], "Size", Size); + Changes.push_back(SetTFRewriteData("Size", Size)); if (DoMD5 == true) - SetTFRewriteData(Changes[End++], "MD5sum", Db.MD5Res.c_str()); + Changes.push_back(SetTFRewriteData("MD5sum", Db.MD5Res.c_str())); if (DoSHA1 == true) - SetTFRewriteData(Changes[End++], "SHA1", Db.SHA1Res.c_str()); + Changes.push_back(SetTFRewriteData("SHA1", Db.SHA1Res.c_str())); if (DoSHA256 == true) - SetTFRewriteData(Changes[End++], "SHA256", Db.SHA256Res.c_str()); + Changes.push_back(SetTFRewriteData("SHA256", Db.SHA256Res.c_str())); if (DoSHA512 == true) - SetTFRewriteData(Changes[End++], "SHA512", Db.SHA512Res.c_str()); - SetTFRewriteData(Changes[End++], "Filename", NewFileName.c_str()); - SetTFRewriteData(Changes[End++], "Priority", OverItem->Priority.c_str()); - SetTFRewriteData(Changes[End++], "Status", 0); - SetTFRewriteData(Changes[End++], "Optional", 0); + Changes.push_back(SetTFRewriteData("SHA512", Db.SHA512Res.c_str())); + Changes.push_back(SetTFRewriteData("Filename", NewFileName.c_str())); + Changes.push_back(SetTFRewriteData("Priority", OverItem->Priority.c_str())); + Changes.push_back(SetTFRewriteData("Status", 0)); + Changes.push_back(SetTFRewriteData("Optional", 0)); string DescriptionMd5; if (LongDescription == false) { MD5Summation descmd5; descmd5.Add(desc.c_str()); DescriptionMd5 = descmd5.Result().Value(); - SetTFRewriteData(Changes[End++], "Description-md5", DescriptionMd5.c_str()); + Changes.push_back(SetTFRewriteData("Description-md5", DescriptionMd5.c_str())); if (TransWriter != NULL) TransWriter->DoPackage(Package, desc, DescriptionMd5); } @@ -476,12 +491,12 @@ bool PackagesWriter::DoPackage(string FileName) NewLine(1); ioprintf(c1out, _(" %s maintainer is %s not %s\n"), Package.c_str(), Tags.FindS("Maintainer").c_str(), OverItem->OldMaint.c_str()); - } + } } - + if (NewMaint.empty() == false) - SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str()); - + Changes.push_back(SetTFRewriteData("Maintainer", NewMaint.c_str())); + /* Get rid of the Optional tag. This is an ugly, ugly, ugly hack that dpkg-scanpackages does. Well sort of. dpkg-scanpackages just does renaming but dpkg does this append bit. So we do the append bit, at least that way the @@ -492,17 +507,17 @@ bool PackagesWriter::DoPackage(string FileName) { if (Tags.FindS("Suggests").empty() == false) OptionalStr = Tags.FindS("Suggests") + ", " + OptionalStr; - SetTFRewriteData(Changes[End++], "Suggests", OptionalStr.c_str()); + Changes.push_back(SetTFRewriteData("Suggests", OptionalStr.c_str())); } - for (map::const_iterator I = OverItem->FieldOverride.begin(); + for (map::const_iterator I = OverItem->FieldOverride.begin(); I != OverItem->FieldOverride.end(); ++I) - SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str()); + Changes.push_back(SetTFRewriteData(I->first.c_str(),I->second.c_str())); - SetTFRewriteData(Changes[End++], 0, 0); + Changes.push_back(SetTFRewriteData( 0, 0)); // Rewrite and store the fields. - if (TFRewrite(Output,Tags,TFRewritePackageOrder,Changes) == false) + if (TFRewrite(Output,Tags,TFRewritePackageOrder,Changes.data()) == false) return false; fprintf(Output,"\n"); @@ -562,8 +577,9 @@ TranslationWriter::~TranslationWriter() // SourcesWriter::SourcesWriter - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -SourcesWriter::SourcesWriter(string const &BOverrides,string const &SOverrides, - string const &ExtOverrides) +SourcesWriter::SourcesWriter(string const &DB, string const &BOverrides,string const &SOverrides, + string const &ExtOverrides) : + Db(DB), Stats(Db.Stats) { Output = stdout; AddPattern("*.dsc"); @@ -575,7 +591,9 @@ SourcesWriter::SourcesWriter(string const &BOverrides,string const &SOverrides, DoMD5 = _config->FindB("APT::FTPArchive::Sources::MD5",DoMD5); DoSHA1 = _config->FindB("APT::FTPArchive::Sources::SHA1",DoSHA1); DoSHA256 = _config->FindB("APT::FTPArchive::Sources::SHA256",DoSHA256); + DoSHA512 = _config->FindB("APT::FTPArchive::Sources::SHA512",DoSHA512); NoOverride = _config->FindB("APT::FTPArchive::NoOverrideMsg",false); + DoAlwaysStat = _config->FindB("APT::FTPArchive::AlwaysStat", false); // Read the override file if (BOverrides.empty() == false && BOver.ReadOverride(BOverrides) == false) @@ -598,77 +616,39 @@ SourcesWriter::SourcesWriter(string const &BOverrides,string const &SOverrides, // --------------------------------------------------------------------- /* */ bool SourcesWriter::DoPackage(string FileName) -{ - // Open the archive - FileFd F(FileName,FileFd::ReadOnly); - if (_error->PendingError() == true) - return false; - - // Stat the file for later - struct stat St; - if (fstat(F.Fd(),&St) != 0) - return _error->Errno("fstat","Failed to stat %s",FileName.c_str()); - - if (St.st_size > 128*1024) - return _error->Error("DSC file '%s' is too large!",FileName.c_str()); - - if (BufSize < (unsigned long long)St.st_size+1) +{ + // Pull all the data we need form the DB + if (Db.GetFileInfo(FileName, + false, /* DoControl */ + false, /* DoContents */ + false, /* GenContentsOnly */ + true, /* DoSource */ + DoMD5, DoSHA1, DoSHA256, DoSHA512, DoAlwaysStat) == false) { - BufSize = St.st_size+1; - Buffer = (char *)realloc(Buffer,St.st_size+1); - } - - if (F.Read(Buffer,St.st_size) == false) return false; + } - // Hash the file - char *Start = Buffer; - char *BlkEnd = Buffer + St.st_size; + // we need to perform a "write" here (this is what finish is doing) + // because the call to Db.GetFileInfo() in the loop will change + // the "db cursor" + Db.Finish(); - MD5Summation MD5; - SHA1Summation SHA1; - SHA256Summation SHA256; - SHA256Summation SHA512; + // read stuff + char *Start = Db.Dsc.Data; + char *BlkEnd = Db.Dsc.Data + Db.Dsc.Length; - if (DoMD5 == true) - MD5.Add((unsigned char *)Start,BlkEnd - Start); - if (DoSHA1 == true) - SHA1.Add((unsigned char *)Start,BlkEnd - Start); - if (DoSHA256 == true) - SHA256.Add((unsigned char *)Start,BlkEnd - Start); - if (DoSHA512 == true) - SHA512.Add((unsigned char *)Start,BlkEnd - Start); - - // Add an extra \n to the end, just in case + // Add extra \n to the end, just in case (as in clearsigned they are missing) *BlkEnd++ = '\n'; - - /* Remove the PGP trailer. Some .dsc's have this without a blank line - before */ - const char *Key = "-----BEGIN PGP SIGNATURE-----"; - for (char *MsgEnd = Start; MsgEnd < BlkEnd - strlen(Key) -1; MsgEnd++) - { - if (*MsgEnd == '\n' && strncmp(MsgEnd+1,Key,strlen(Key)) == 0) - { - MsgEnd[1] = '\n'; - break; - } - } - - /* Read records until we locate the Source record. This neatly skips the - GPG header (which is RFC822 formed) without any trouble. */ + *BlkEnd++ = '\n'; + pkgTagSection Tags; - do - { - unsigned Pos; - if (Tags.Scan(Start,BlkEnd - Start) == false) - return _error->Error("Could not find a record in the DSC '%s'",FileName.c_str()); - if (Tags.Find("Source",Pos) == true) - break; - Start += Tags.size(); - } - while (1); + if (Tags.Scan(Start,BlkEnd - Start) == false) + return _error->Error("Could not find a record in the DSC '%s'",FileName.c_str()); + + if (Tags.Exists("Source") == false) + return _error->Error("Could not find a Source entry in the DSC '%s'",FileName.c_str()); Tags.Trim(); - + // Lookup the overide information, finding first the best priority. string BestPrio; string Bins = Tags.FindS("Binary"); @@ -714,6 +694,10 @@ bool SourcesWriter::DoPackage(string FileName) OverItem = auto_ptr(new Override::Item); } + struct stat St; + if (stat(FileName.c_str(), &St) != 0) + return _error->Errno("fstat","Failed to stat %s",FileName.c_str()); + auto_ptr SOverItem(SOver.GetItem(Tags.FindS("Source"))); // const auto_ptr autoSOverItem(SOverItem); if (SOverItem.get() == 0) @@ -732,27 +716,24 @@ bool SourcesWriter::DoPackage(string FileName) string const strippedName = flNotDir(FileName); std::ostringstream ostreamFiles; if (DoMD5 == true && Tags.Exists("Files")) - ostreamFiles << "\n " << string(MD5.Result()) << " " << St.st_size << " " + ostreamFiles << "\n " << Db.MD5Res.c_str() << " " << St.st_size << " " << strippedName << "\n " << Tags.FindS("Files"); string const Files = ostreamFiles.str(); std::ostringstream ostreamSha1; if (DoSHA1 == true && Tags.Exists("Checksums-Sha1")) - ostreamSha1 << "\n " << string(SHA1.Result()) << " " << St.st_size << " " + ostreamSha1 << "\n " << string(Db.SHA1Res.c_str()) << " " << St.st_size << " " << strippedName << "\n " << Tags.FindS("Checksums-Sha1"); - string const ChecksumsSha1 = ostreamSha1.str(); std::ostringstream ostreamSha256; if (DoSHA256 == true && Tags.Exists("Checksums-Sha256")) - ostreamSha256 << "\n " << string(SHA256.Result()) << " " << St.st_size << " " + ostreamSha256 << "\n " << string(Db.SHA256Res.c_str()) << " " << St.st_size << " " << strippedName << "\n " << Tags.FindS("Checksums-Sha256"); - string const ChecksumsSha256 = ostreamSha256.str(); std::ostringstream ostreamSha512; - if (Tags.Exists("Checksums-Sha512")) - ostreamSha512 << "\n " << string(SHA512.Result()) << " " << St.st_size << " " + if (DoSHA512 == true && Tags.Exists("Checksums-Sha512")) + ostreamSha512 << "\n " << string(Db.SHA512Res.c_str()) << " " << St.st_size << " " << strippedName << "\n " << Tags.FindS("Checksums-Sha512"); - string const ChecksumsSha512 = ostreamSha512.str(); // Strip the DirStrip prefix from the FileName and add the PathPrefix string NewFileName; @@ -768,7 +749,7 @@ bool SourcesWriter::DoPackage(string FileName) string Directory = flNotFile(OriginalPath); string Package = Tags.FindS("Source"); - // Perform the delinking operation over all of the files + // Perform operation over all of the files string ParseJnk; const char *C = Files.c_str(); char *RealPath = NULL; @@ -780,9 +761,44 @@ bool SourcesWriter::DoPackage(string FileName) ParseQuoteWord(C,ParseJnk) == false || ParseQuoteWord(C,ParseJnk) == false) return _error->Error("Error parsing file record"); - - char Jnk[2]; + string OriginalPath = Directory + ParseJnk; + + // Add missing hashes to source files + if ((DoSHA1 == true && !Tags.Exists("Checksums-Sha1")) || + (DoSHA256 == true && !Tags.Exists("Checksums-Sha256")) || + (DoSHA512 == true && !Tags.Exists("Checksums-Sha512"))) + { + if (Db.GetFileInfo(OriginalPath, + false, /* DoControl */ + false, /* DoContents */ + false, /* GenContentsOnly */ + false, /* DoSource */ + DoMD5, DoSHA1, DoSHA256, DoSHA512, + DoAlwaysStat) == false) + { + return _error->Error("Error getting file info"); + } + + if (DoSHA1 == true && !Tags.Exists("Checksums-Sha1")) + ostreamSha1 << "\n " << string(Db.SHA1Res) << " " + << Db.GetFileSize() << " " << ParseJnk; + + if (DoSHA256 == true && !Tags.Exists("Checksums-Sha256")) + ostreamSha256 << "\n " << string(Db.SHA256Res) << " " + << Db.GetFileSize() << " " << ParseJnk; + + if (DoSHA512 == true && !Tags.Exists("Checksums-Sha512")) + ostreamSha512 << "\n " << string(Db.SHA512Res) << " " + << Db.GetFileSize() << " " << ParseJnk; + + // write back the GetFileInfo() stats data + Db.Finish(); + } + + // Perform the delinking operation + char Jnk[2]; + if (readlink(OriginalPath.c_str(),Jnk,sizeof(Jnk)) != -1 && (RealPath = realpath(OriginalPath.c_str(),NULL)) != 0) { @@ -797,24 +813,27 @@ bool SourcesWriter::DoPackage(string FileName) if (Directory.length() > 2) Directory.erase(Directory.end()-1); + string const ChecksumsSha1 = ostreamSha1.str(); + string const ChecksumsSha256 = ostreamSha256.str(); + string const ChecksumsSha512 = ostreamSha512.str(); + // This lists all the changes to the fields we are going to make. // (5 hardcoded + checksums + maintainer + end marker) - TFRewriteData Changes[5+2+1+SOverItem->FieldOverride.size()+1]; + std::vector Changes; - unsigned int End = 0; - SetTFRewriteData(Changes[End++],"Source",Package.c_str(),"Package"); + Changes.push_back(SetTFRewriteData("Source",Package.c_str(),"Package")); if (Files.empty() == false) - SetTFRewriteData(Changes[End++],"Files",Files.c_str()); + Changes.push_back(SetTFRewriteData("Files",Files.c_str())); if (ChecksumsSha1.empty() == false) - SetTFRewriteData(Changes[End++],"Checksums-Sha1",ChecksumsSha1.c_str()); + Changes.push_back(SetTFRewriteData("Checksums-Sha1",ChecksumsSha1.c_str())); if (ChecksumsSha256.empty() == false) - SetTFRewriteData(Changes[End++],"Checksums-Sha256",ChecksumsSha256.c_str()); + Changes.push_back(SetTFRewriteData("Checksums-Sha256",ChecksumsSha256.c_str())); if (ChecksumsSha512.empty() == false) - SetTFRewriteData(Changes[End++],"Checksums-Sha512",ChecksumsSha512.c_str()); + Changes.push_back(SetTFRewriteData("Checksums-Sha512",ChecksumsSha512.c_str())); if (Directory != "./") - SetTFRewriteData(Changes[End++],"Directory",Directory.c_str()); - SetTFRewriteData(Changes[End++],"Priority",BestPrio.c_str()); - SetTFRewriteData(Changes[End++],"Status",0); + Changes.push_back(SetTFRewriteData("Directory",Directory.c_str())); + Changes.push_back(SetTFRewriteData("Priority",BestPrio.c_str())); + Changes.push_back(SetTFRewriteData("Status",0)); // Rewrite the maintainer field if necessary bool MaintFailed; @@ -829,16 +848,16 @@ bool SourcesWriter::DoPackage(string FileName) } } if (NewMaint.empty() == false) - SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str()); + Changes.push_back(SetTFRewriteData("Maintainer", NewMaint.c_str())); for (map::const_iterator I = SOverItem->FieldOverride.begin(); I != SOverItem->FieldOverride.end(); ++I) - SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str()); + Changes.push_back(SetTFRewriteData(I->first.c_str(),I->second.c_str())); - SetTFRewriteData(Changes[End++], 0, 0); + Changes.push_back(SetTFRewriteData(0, 0)); // Rewrite and store the fields. - if (TFRewrite(Output,Tags,TFRewriteSourceOrder,Changes) == false) + if (TFRewrite(Output,Tags,TFRewriteSourceOrder,Changes.data()) == false) return false; fprintf(Output,"\n"); @@ -865,7 +884,15 @@ ContentsWriter::ContentsWriter(string const &DB, string const &Arch) : determine what the package name is. */ bool ContentsWriter::DoPackage(string FileName, string Package) { - if (!Db.GetFileInfo(FileName, Package.empty(), true, false, false, false, false, false)) + if (!Db.GetFileInfo(FileName, + Package.empty(), /* DoControl */ + true, /* DoContents */ + false, /* GenContentsOnly */ + false, /* DoSource */ + false, /* DoMD5 */ + false, /* DoSHA1 */ + false, /* DoSHA256 */ + false)) /* DoSHA512 */ { return false; } @@ -932,7 +959,7 @@ bool ContentsWriter::ReadFromPkgs(string const &PkgFile,string const &PkgCompres // ReleaseWriter::ReleaseWriter - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -ReleaseWriter::ReleaseWriter(string const &DB) +ReleaseWriter::ReleaseWriter(string const &/*DB*/) { if (_config->FindB("APT::FTPArchive::Release::Default-Patterns", true) == true) { @@ -941,12 +968,14 @@ ReleaseWriter::ReleaseWriter(string const &DB) AddPattern("Packages.bz2"); AddPattern("Packages.lzma"); AddPattern("Packages.xz"); + AddPattern("Translation-*"); AddPattern("Sources"); AddPattern("Sources.gz"); AddPattern("Sources.bz2"); AddPattern("Sources.lzma"); AddPattern("Sources.xz"); AddPattern("Release"); + AddPattern("Contents-*"); AddPattern("Index"); AddPattern("md5sum.txt"); }