X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/8c4e1f97686c412f88bb57827a84b776626d9980..1701312682aad167b4ff3425a8e9b680c04b49a5:/ftparchive/writer.cc?ds=sidebyside diff --git a/ftparchive/writer.cc b/ftparchive/writer.cc index 60db8b990..153c4fb42 100644 --- a/ftparchive/writer.cc +++ b/ftparchive/writer.cc @@ -11,29 +11,42 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#include "writer.h" - -#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 "cachedb.h" +#include + #include "apt-ftparchive.h" +#include "writer.h" +#include "cachedb.h" #include "multicompress.h" + +#include /*}}}*/ using namespace std; FTWScanner *FTWScanner::Owner; @@ -68,9 +81,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) { @@ -246,8 +259,8 @@ bool FTWScanner::LoadFileList(string const &Dir, string const &File) // --------------------------------------------------------------------- /* */ bool FTWScanner::Delink(string &FileName,const char *OriginalPath, - unsigned long &DeLinkBytes, - off_t const &FileSize) + unsigned long long &DeLinkBytes, + unsigned long long const &FileSize) { // See if this isn't an internaly prefix'd file name. if (InternalPrefix.empty() == false && @@ -280,7 +293,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); @@ -316,7 +330,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); @@ -377,7 +391,7 @@ bool PackagesWriter::DoPackage(string FileName) return false; } - off_t FileSize = Db.GetFileSize(); + unsigned long long FileSize = Db.GetFileSize(); if (Delink(FileName,OriginalPath,Stats.DeLinkBytes,FileSize) == false) return false; @@ -413,7 +427,7 @@ bool PackagesWriter::DoPackage(string FileName) } char Size[40]; - sprintf(Size,"%lu", (unsigned long) FileSize); + sprintf(Size,"%llu", (unsigned long long) FileSize); // Strip the DirStrip prefix from the FileName and add the PathPrefix string NewFileName; @@ -494,7 +508,7 @@ bool PackagesWriter::DoPackage(string FileName) } for (map::const_iterator I = OverItem->FieldOverride.begin(); - I != OverItem->FieldOverride.end(); I++) + I != OverItem->FieldOverride.end(); ++I) SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str()); SetTFRewriteData(Changes[End++], 0, 0); @@ -560,8 +574,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"); @@ -573,7 +588,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) @@ -596,77 +613,62 @@ 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) + FileFd F; + if (OpenMaybeClearSignedFile(FileName, F) == false) 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) + unsigned long long const FSize = F.FileSize(); + //FIXME: do we really need to enforce a maximum size of the dsc file? + if (FSize > 128*1024) return _error->Error("DSC file '%s' is too large!",FileName.c_str()); - - if (BufSize < (unsigned)St.st_size+1) + + if (BufSize < FSize + 2) { - BufSize = St.st_size+1; - Buffer = (char *)realloc(Buffer,St.st_size+1); + BufSize = FSize + 2; + Buffer = (char *)realloc(Buffer , BufSize); } - - if (F.Read(Buffer,St.st_size) == false) + + if (F.Read(Buffer, FSize) == false) return false; + // Stat the file for later (F might be clearsigned, so not F.FileSize()) + struct stat St; + if (stat(FileName.c_str(), &St) != 0) + return _error->Errno("fstat","Failed to stat %s",FileName.c_str()); + // Hash the file char *Start = Buffer; - char *BlkEnd = Buffer + St.st_size; - - MD5Summation MD5; - SHA1Summation SHA1; - SHA256Summation SHA256; - SHA256Summation SHA512; + char *BlkEnd = Buffer + FSize; - 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 - *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++) + Hashes DscHashes; + if (FSize == (unsigned long long) St.st_size) { - if (*MsgEnd == '\n' && strncmp(MsgEnd+1,Key,strlen(Key)) == 0) - { - MsgEnd[1] = '\n'; - break; - } + if (DoMD5 == true) + DscHashes.MD5.Add((unsigned char *)Start,BlkEnd - Start); + if (DoSHA1 == true) + DscHashes.SHA1.Add((unsigned char *)Start,BlkEnd - Start); + if (DoSHA256 == true) + DscHashes.SHA256.Add((unsigned char *)Start,BlkEnd - Start); + if (DoSHA512 == true) + DscHashes.SHA512.Add((unsigned char *)Start,BlkEnd - Start); } - - /* Read records until we locate the Source record. This neatly skips the - GPG header (which is RFC822 formed) without any trouble. */ - pkgTagSection Tags; - do + else { - 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(); + FileFd DscFile(FileName, FileFd::ReadOnly); + DscHashes.AddFD(DscFile, St.st_size, DoMD5, DoSHA1, DoSHA256, DoSHA512); } - while (1); + + // Add extra \n to the end, just in case (as in clearsigned they are missing) + *BlkEnd++ = '\n'; + *BlkEnd++ = '\n'; + + pkgTagSection Tags; + if (Tags.Scan(Start,BlkEnd - Start) == false || Tags.Exists("Source") == false) + return _error->Error("Could not find a record 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"); @@ -730,27 +732,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 " << string(DscHashes.MD5.Result()) << " " << 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(DscHashes.SHA1.Result()) << " " << 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(DscHashes.SHA256.Result()) << " " << 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(DscHashes.SHA512.Result()) << " " << 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; @@ -766,7 +765,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; @@ -778,9 +777,36 @@ 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, false, false, 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; + } + + // Perform the delinking operation + char Jnk[2]; + if (readlink(OriginalPath.c_str(),Jnk,sizeof(Jnk)) != -1 && (RealPath = realpath(OriginalPath.c_str(),NULL)) != 0) { @@ -795,6 +821,10 @@ 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]; @@ -830,7 +860,7 @@ bool SourcesWriter::DoPackage(string FileName) SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str()); for (map::const_iterator I = SOverItem->FieldOverride.begin(); - I != SOverItem->FieldOverride.end(); I++) + I != SOverItem->FieldOverride.end(); ++I) SetTFRewriteData(Changes[End++],I->first.c_str(),I->second.c_str()); SetTFRewriteData(Changes[End++], 0, 0); @@ -842,7 +872,7 @@ bool SourcesWriter::DoPackage(string FileName) Stats.Packages++; - return true; + return Db.Finish(); } /*}}}*/ @@ -887,22 +917,16 @@ bool ContentsWriter::ReadFromPkgs(string const &PkgFile,string const &PkgCompres MultiCompress Pkgs(PkgFile,PkgCompress,0,false); if (_error->PendingError() == true) return false; - + // Open the package file - int CompFd = -1; - pid_t Proc = -1; - if (Pkgs.OpenOld(CompFd,Proc) == false) + FileFd Fd; + if (Pkgs.OpenOld(Fd) == false) return false; - - // No auto-close FD - FileFd Fd(CompFd,false); + pkgTagFile Tags(&Fd); if (_error->PendingError() == true) - { - Pkgs.CloseOld(CompFd,Proc); return false; - } - + // Parse. pkgTagSection Section; while (Tags.Step(Section) == true) @@ -924,11 +948,10 @@ bool ContentsWriter::ReadFromPkgs(string const &PkgFile,string const &PkgCompres _error->DumpErrors(); } } - + // Tidy the compressor - if (Pkgs.CloseOld(CompFd,Proc) == false) - return false; - + Fd.Close(); + return true; } @@ -937,7 +960,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) { @@ -946,12 +969,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"); } @@ -1040,7 +1065,7 @@ bool ReleaseWriter::DoPackage(string FileName) CheckSums[NewFileName].size = fd.Size(); Hashes hs; - hs.AddFD(fd.Fd(), 0, DoMD5, DoSHA1, DoSHA256, DoSHA512); + hs.AddFD(fd, 0, DoMD5, DoSHA1, DoSHA256, DoSHA512); if (DoMD5 == true) CheckSums[NewFileName].MD5 = hs.MD5.Result(); if (DoSHA1 == true) @@ -1065,7 +1090,7 @@ void ReleaseWriter::Finish() for(map::const_iterator I = CheckSums.begin(); I != CheckSums.end(); ++I) { - fprintf(Output, " %s %16ld %s\n", + fprintf(Output, " %s %16llu %s\n", (*I).second.MD5.c_str(), (*I).second.size, (*I).first.c_str()); @@ -1077,7 +1102,7 @@ void ReleaseWriter::Finish() for(map::const_iterator I = CheckSums.begin(); I != CheckSums.end(); ++I) { - fprintf(Output, " %s %16ld %s\n", + fprintf(Output, " %s %16llu %s\n", (*I).second.SHA1.c_str(), (*I).second.size, (*I).first.c_str()); @@ -1089,7 +1114,7 @@ void ReleaseWriter::Finish() for(map::const_iterator I = CheckSums.begin(); I != CheckSums.end(); ++I) { - fprintf(Output, " %s %16ld %s\n", + fprintf(Output, " %s %16llu %s\n", (*I).second.SHA256.c_str(), (*I).second.size, (*I).first.c_str()); @@ -1101,7 +1126,7 @@ void ReleaseWriter::Finish() I != CheckSums.end(); ++I) { - fprintf(Output, " %s %32ld %s\n", + fprintf(Output, " %s %16llu %s\n", (*I).second.SHA512.c_str(), (*I).second.size, (*I).first.c_str());