]> git.saurik.com Git - apt.git/blobdiff - ftparchive/writer.cc
Merge branch 'feature/edit-sources' into debian/sid
[apt.git] / ftparchive / writer.cc
index 60db8b9907a949541e2edc08efe78da93bd9b495..7ecfe78ede2172c404003ab4dcffac11a9af0a71 100644 (file)
@@ -11,9 +11,8 @@
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
-#include "writer.h"
-    
-#include <apti18n.h>
+#include <config.h>
+
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
@@ -21,6 +20,8 @@
 #include <apt-pkg/md5.h>
 #include <apt-pkg/hashes.h>
 #include <apt-pkg/deblistparser.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/gpgv.h>
 
 #include <sys/types.h>
 #include <unistd.h>
 #include <iostream>
 #include <sstream>
 #include <memory>
-    
+
+#include "writer.h"
 #include "cachedb.h"
 #include "apt-ftparchive.h"
 #include "multicompress.h"
+
+#include <apti18n.h>
                                                                        /*}}}*/
 using namespace std;
 FTWScanner *FTWScanner::Owner;
@@ -246,8 +250,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 +284,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 +321,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 +382,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 +418,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 +499,7 @@ bool PackagesWriter::DoPackage(string FileName)
    }
 
    for (map<string,string>::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 +565,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 +579,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 +604,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 +723,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 +756,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 +768,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 +812,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 +851,7 @@ bool SourcesWriter::DoPackage(string FileName)
       SetTFRewriteData(Changes[End++], "Maintainer", NewMaint.c_str());
    
    for (map<string,string>::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 +863,7 @@ bool SourcesWriter::DoPackage(string FileName)
 
    Stats.Packages++;
    
-   return true;
+   return Db.Finish();
 }
                                                                        /*}}}*/
 
@@ -887,22 +908,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 +939,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;
 }
 
@@ -946,12 +960,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 +1056,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 +1081,7 @@ void ReleaseWriter::Finish()
       for(map<string,struct CheckSum>::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 +1093,7 @@ void ReleaseWriter::Finish()
       for(map<string,struct CheckSum>::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 +1105,7 @@ void ReleaseWriter::Finish()
       for(map<string,struct CheckSum>::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 +1117,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());