]> git.saurik.com Git - apt.git/blobdiff - ftparchive/writer.cc
use a std::vector instead of hardcoded array
[apt.git] / ftparchive / writer.cc
index 3283128d81a52ec297dc43f485ceed538b549d98..83c0b1e3fa5373e07da0d6333f58c9759aa9b74b 100644 (file)
 // Include Files                                                       /*{{{*/
 #include <config.h>
 
-#include <apt-pkg/strutl.h>
-#include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
-#include <apt-pkg/aptconfiguration.h>
-#include <apt-pkg/md5.h>
-#include <apt-pkg/hashes.h>
 #include <apt-pkg/deblistparser.h>
+#include <apt-pkg/error.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/gpgv.h>
+#include <apt-pkg/hashes.h>
+#include <apt-pkg/md5.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/debfile.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/sha1.h>
+#include <apt-pkg/sha2.h>
+#include <apt-pkg/tagfile.h>
 
+#include <ctype.h>
+#include <fnmatch.h>
+#include <ftw.h>
+#include <locale.h>
+#include <string.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <ctime>
-#include <ftw.h>
-#include <fnmatch.h>
 #include <iostream>
 #include <sstream>
 #include <memory>
+#include <utility>
 
+#include "apt-ftparchive.h"
 #include "writer.h"
 #include "cachedb.h"
-#include "apt-ftparchive.h"
 #include "multicompress.h"
 
 #include <apti18n.h>
@@ -45,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;
 }
                                                                        /*}}}*/
 
@@ -72,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)
    {
@@ -284,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);
@@ -375,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();
@@ -440,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<TFRewriteData> 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);
    }
@@ -478,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
@@ -494,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<string,string>::const_iterator I = OverItem->FieldOverride.begin(); 
+   for (map<string,string>::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");
 
@@ -604,59 +617,36 @@ SourcesWriter::SourcesWriter(string const &DB, string const &BOverrides,string c
 /* */
 bool SourcesWriter::DoPackage(string FileName)
 {
-   // Open the archive
-   FileFd F;
-   if (OpenMaybeClearSignedFile(FileName, F) == false)
-      return false;
-
-   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 < FSize + 2)
+   // 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 = FSize + 2;
-      Buffer = (char *)realloc(Buffer , BufSize);
-   }
-
-   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 + FSize;
+   // 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();
 
-   Hashes DscHashes;
-   if (FSize == (unsigned long long) St.st_size)
-   {
-      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);
-   }
-   else
-   {
-      FileFd DscFile(FileName, FileFd::ReadOnly);
-      DscHashes.AddFD(DscFile, St.st_size, DoMD5, DoSHA1, DoSHA256, DoSHA512);
-   }
+   // read stuff
+   char *Start = Db.Dsc.Data;
+   char *BlkEnd = Db.Dsc.Data + Db.Dsc.Length;
 
    // 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)
+   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.
@@ -704,6 +694,10 @@ bool SourcesWriter::DoPackage(string FileName)
       OverItem = auto_ptr<Override::Item>(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<Override::Item> SOverItem(SOver.GetItem(Tags.FindS("Source")));
    // const auto_ptr<Override::Item> autoSOverItem(SOverItem);
    if (SOverItem.get() == 0)
@@ -722,23 +716,23 @@ bool SourcesWriter::DoPackage(string FileName)
    string const strippedName = flNotDir(FileName);
    std::ostringstream ostreamFiles;
    if (DoMD5 == true && Tags.Exists("Files"))
-      ostreamFiles << "\n " << string(DscHashes.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(DscHashes.SHA1.Result()) << " " << St.st_size << " "
+      ostreamSha1 << "\n " << string(Db.SHA1Res.c_str()) << " " << St.st_size << " "
                   << strippedName << "\n " << Tags.FindS("Checksums-Sha1");
 
    std::ostringstream ostreamSha256;
    if (DoSHA256 == true && Tags.Exists("Checksums-Sha256"))
-      ostreamSha256 << "\n " << string(DscHashes.SHA256.Result()) << " " << St.st_size << " "
+      ostreamSha256 << "\n " << string(Db.SHA256Res.c_str()) << " " << St.st_size << " "
                   << strippedName << "\n " << Tags.FindS("Checksums-Sha256");
 
    std::ostringstream ostreamSha512;
    if (DoSHA512 == true && Tags.Exists("Checksums-Sha512"))
-      ostreamSha512 << "\n " << string(DscHashes.SHA512.Result()) << " " << St.st_size << " "
+      ostreamSha512 << "\n " << string(Db.SHA512Res.c_str()) << " " << St.st_size << " "
                   << strippedName << "\n " << Tags.FindS("Checksums-Sha512");
 
    // Strip the DirStrip prefix from the FileName and add the PathPrefix
@@ -775,8 +769,13 @@ bool SourcesWriter::DoPackage(string FileName)
           (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)
+         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");
          }
@@ -792,6 +791,9 @@ bool SourcesWriter::DoPackage(string FileName)
          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
@@ -817,22 +819,21 @@ bool SourcesWriter::DoPackage(string FileName)
 
    // 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<TFRewriteData> 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;
@@ -847,22 +848,22 @@ 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<string,string>::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");
 
    Stats.Packages++;
    
-   return Db.Finish();
+   return true;
 }
                                                                        /*}}}*/
 
@@ -883,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;
    }
@@ -950,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)
    {