]> git.saurik.com Git - apt.git/blobdiff - ftparchive/writer.cc
headers are for declarations only
[apt.git] / ftparchive / writer.cc
index a63d8846b155a92aee3622612218e4cdc9954ca3..1bc926d2157dcea06f457b7dc89d435f7e21862f 100644 (file)
 using namespace std;
 FTWScanner *FTWScanner::Owner;
 
-// SetTFRewriteData - Helper for setting rewrite lists                 /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-static inline TFRewriteData SetTFRewriteData(const char *tag,
-                            const char *rewrite,
-                            const char *newtag = 0)
-{
-   TFRewriteData tfrd;
-   tfrd.Tag = tag;
-   tfrd.Rewrite = rewrite;
-   tfrd.NewTag = newtag;
-   return tfrd;
-}
-                                                                       /*}}}*/
 // ConfigToDoHashes - which hashes to generate                         /*{{{*/
 static void SingleConfigToDoHashes(unsigned int &DoHashes, std::string const &Conf, unsigned int const Flag)
 {
@@ -83,15 +69,29 @@ static void ConfigToDoHashes(unsigned int &DoHashes, std::string const &Conf)
                                                                        /*}}}*/
 
 // FTWScanner::FTWScanner - Constructor                                        /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-FTWScanner::FTWScanner(string const &Arch): Arch(Arch), DoHashes(~0)
+FTWScanner::FTWScanner(FileFd * const GivenOutput, string const &Arch): Arch(Arch), DoHashes(~0)
 {
+   if (GivenOutput == NULL)
+   {
+      Output = new FileFd;
+      OwnsOutput = true;
+      Output->OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly, false);
+   }
+   else
+   {
+      Output = GivenOutput;
+      OwnsOutput = false;
+   }
    ErrorPrinted = false;
    NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true);
    ConfigToDoHashes(DoHashes, "APT::FTPArchive");
 }
                                                                        /*}}}*/
+FTWScanner::~FTWScanner()
+{
+   if (Output != NULL && OwnsOutput)
+      delete Output;
+}
 // FTWScanner::Scanner - FTW Scanner                                   /*{{{*/
 // ---------------------------------------------------------------------
 /* This is the FTW scanner, it processes each directory element in the
@@ -331,11 +331,11 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
 // PackagesWriter::PackagesWriter - Constructor                                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string const &ExtOverrides,
-                              string const &Arch) :
-   FTWScanner(Arch), Db(DB), Stats(Db.Stats), TransWriter(NULL)
+PackagesWriter::PackagesWriter(FileFd * const GivenOutput, TranslationWriter * const transWriter,
+      string const &DB,string const &Overrides,string const &ExtOverrides,
+      string const &Arch) :
+   FTWScanner(GivenOutput, Arch), Db(DB), Stats(Db.Stats), TransWriter(transWriter)
 {
-   Output = stdout;
    SetExts(".deb .udeb");
    DeLinkLimit = 0;
 
@@ -385,7 +385,6 @@ bool FTWScanner::SetExts(string const &Vals)
 
    return true;
 }
-
                                                                        /*}}}*/
 // PackagesWriter::DoPackage - Process a single package                        /*{{{*/
 // ---------------------------------------------------------------------
@@ -440,9 +439,6 @@ bool PackagesWriter::DoPackage(string FileName)
       OverItem->Priority = Tags.FindS("Priority");
    }
 
-   char Size[40];
-   sprintf(Size,"%llu", (unsigned long long) FileSize);
-   
    // Strip the DirStrip prefix from the FileName and add the PathPrefix
    string NewFileName;
    if (DirStrip.empty() == false &&
@@ -464,29 +460,32 @@ bool PackagesWriter::DoPackage(string FileName)
    }
 
    // This lists all the changes to the fields we are going to make.
-   std::vector<TFRewriteData> Changes;
+   std::vector<pkgTagSection::Tag> Changes;
+
+   std::string Size;
+   strprintf(Size, "%llu", (unsigned long long) FileSize);
+   Changes.push_back(pkgTagSection::Tag::Rewrite("Size", Size));
 
-   Changes.push_back(SetTFRewriteData("Size", Size));
    for (HashStringList::const_iterator hs = Db.HashesList.begin(); hs != Db.HashesList.end(); ++hs)
    {
       if (hs->HashType() == "MD5Sum")
-        Changes.push_back(SetTFRewriteData("MD5sum", hs->HashValue().c_str()));
+        Changes.push_back(pkgTagSection::Tag::Rewrite("MD5sum", hs->HashValue()));
       else if (hs->HashType() == "Checksum-FileSize")
         continue;
       else
-        Changes.push_back(SetTFRewriteData(hs->HashType().c_str(), hs->HashValue().c_str()));
+        Changes.push_back(pkgTagSection::Tag::Rewrite(hs->HashType(), hs->HashValue()));
    }
-   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));
+   Changes.push_back(pkgTagSection::Tag::Rewrite("Filename", NewFileName));
+   Changes.push_back(pkgTagSection::Tag::Rewrite("Priority", OverItem->Priority));
+   Changes.push_back(pkgTagSection::Tag::Remove("Status"));
+   Changes.push_back(pkgTagSection::Tag::Remove("Optional"));
 
    string DescriptionMd5;
    if (LongDescription == false) {
       MD5Summation descmd5;
       descmd5.Add(desc.c_str());
       DescriptionMd5 = descmd5.Result().Value();
-      Changes.push_back(SetTFRewriteData("Description-md5", DescriptionMd5.c_str()));
+      Changes.push_back(pkgTagSection::Tag::Rewrite("Description-md5", DescriptionMd5));
       if (TransWriter != NULL)
         TransWriter->DoPackage(Package, desc, DescriptionMd5);
    }
@@ -505,7 +504,7 @@ bool PackagesWriter::DoPackage(string FileName)
    }
 
    if (NewMaint.empty() == false)
-      Changes.push_back(SetTFRewriteData("Maintainer", NewMaint.c_str()));
+      Changes.push_back(pkgTagSection::Tag::Rewrite("Maintainer", NewMaint));
 
    /* 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
@@ -517,36 +516,37 @@ bool PackagesWriter::DoPackage(string FileName)
    {
       if (Tags.FindS("Suggests").empty() == false)
         OptionalStr = Tags.FindS("Suggests") + ", " + OptionalStr;
-      Changes.push_back(SetTFRewriteData("Suggests", OptionalStr.c_str()));
+      Changes.push_back(pkgTagSection::Tag::Rewrite("Suggests", OptionalStr));
    }
 
    for (map<string,string>::const_iterator I = OverItem->FieldOverride.begin();
         I != OverItem->FieldOverride.end(); ++I)
-      Changes.push_back(SetTFRewriteData(I->first.c_str(),I->second.c_str()));
-
-   Changes.push_back(SetTFRewriteData( 0, 0));
+      Changes.push_back(pkgTagSection::Tag::Rewrite(I->first, I->second));
 
    // Rewrite and store the fields.
-   if (TFRewrite(Output,Tags,TFRewritePackageOrder,Changes.data()) == false)
+   if (Tags.Write(*Output, TFRewritePackageOrder, Changes) == false ||
+        Output->Write("\n", 1) == false)
       return false;
-   fprintf(Output,"\n");
 
    return Db.Finish();
 }
                                                                        /*}}}*/
+PackagesWriter::~PackagesWriter()                                      /*{{{*/
+{
+}
+                                                                       /*}}}*/
 
 // TranslationWriter::TranslationWriter - Constructor                  /*{{{*/
 // ---------------------------------------------------------------------
 /* Create a Translation-Master file for this Packages file */
 TranslationWriter::TranslationWriter(string const &File, string const &TransCompress,
-                                       mode_t const &Permissions) : Output(NULL),
-                                                       RefCounter(0)
+                                       mode_t const &Permissions) : Comp(NULL), Output(NULL)
 {
    if (File.empty() == true)
       return;
 
    Comp = new MultiCompress(File, TransCompress, Permissions);
-   Output = Comp->Input;
+   Output = &Comp->Input;
 }
                                                                        /*}}}*/
 // TranslationWriter::DoPackage - Process a single package             /*{{{*/
@@ -565,8 +565,10 @@ bool TranslationWriter::DoPackage(string const &Pkg, string const &Desc,
    if (Included.find(Record) != Included.end())
       return true;
 
-   fprintf(Output, "Package: %s\nDescription-md5: %s\nDescription-en: %s\n",
+   std::string out;
+   strprintf(out, "Package: %s\nDescription-md5: %s\nDescription-en: %s\n",
           Pkg.c_str(), MD5.c_str(), Desc.c_str());
+   Output->Write(out.c_str(), out.length());
 
    Included.insert(Record);
    return true;
@@ -577,21 +579,18 @@ bool TranslationWriter::DoPackage(string const &Pkg, string const &Desc,
 /* */
 TranslationWriter::~TranslationWriter()
 {
-   if (Comp == NULL)
-      return;
-
-   delete Comp;
+   if (Comp != NULL)
+      delete Comp;
 }
                                                                        /*}}}*/
 
 // SourcesWriter::SourcesWriter - Constructor                          /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-SourcesWriter::SourcesWriter(string const &DB, string const &BOverrides,string const &SOverrides,
+SourcesWriter::SourcesWriter(FileFd * const GivenOutput, string const &DB, string const &BOverrides,string const &SOverrides,
                             string const &ExtOverrides) :
-   Db(DB), Stats(Db.Stats)
+   FTWScanner(GivenOutput), Db(DB), Stats(Db.Stats)
 {
-   Output = stdout;
    AddPattern("*.dsc");
    DeLinkLimit = 0;
    Buffer = 0;
@@ -620,15 +619,16 @@ SourcesWriter::SourcesWriter(string const &DB, string const &BOverrides,string c
 }
                                                                        /*}}}*/
 // SourcesWriter::DoPackage - Process a single package                 /*{{{*/
-static std::ostream& addDscHash(std::ostream &out, unsigned int const DoHashes,
+static std::string getDscHash(unsigned int const DoHashes,
       Hashes::SupportedHashes const DoIt, pkgTagSection &Tags, char const * const FieldName,
       HashString const * const Hash, unsigned long long Size, std::string FileName)
 {
    if ((DoHashes & DoIt) != DoIt || Tags.Exists(FieldName) == false || Hash == NULL)
-      return out;
+      return "";
+   std::ostringstream out;
    out << "\n " << Hash->HashValue() << " " << Size << " " << FileName
       << "\n " << Tags.FindS(FieldName);
-   return out;
+   return out.str();
 }
 bool SourcesWriter::DoPackage(string FileName)
 {
@@ -721,16 +721,10 @@ bool SourcesWriter::DoPackage(string FileName)
 
    // Add the dsc to the files hash list
    string const strippedName = flNotDir(FileName);
-   std::ostringstream ostreamFiles;
-   addDscHash(ostreamFiles, DoHashes, Hashes::MD5SUM, Tags, "Files", Db.HashesList.find("MD5Sum"), St.st_size, strippedName);
-   string const Files = ostreamFiles.str();
-
-   std::ostringstream ostreamSha1;
-   addDscHash(ostreamSha1, DoHashes, Hashes::SHA1SUM, Tags, "Checksums-Sha1", Db.HashesList.find("SHA1"), St.st_size, strippedName);
-   std::ostringstream ostreamSha256;
-   addDscHash(ostreamSha256, DoHashes, Hashes::SHA256SUM, Tags, "Checksums-Sha256", Db.HashesList.find("SHA256"), St.st_size, strippedName);
-   std::ostringstream ostreamSha512;
-   addDscHash(ostreamSha512, DoHashes, Hashes::SHA512SUM, Tags, "Checksums-Sha512", Db.HashesList.find("SHA512"), St.st_size, strippedName);
+   std::string const Files = getDscHash(DoHashes, Hashes::MD5SUM, Tags, "Files", Db.HashesList.find("MD5Sum"), St.st_size, strippedName);
+   std::string ChecksumsSha1 = getDscHash(DoHashes, Hashes::SHA1SUM, Tags, "Checksums-Sha1", Db.HashesList.find("SHA1"), St.st_size, strippedName);
+   std::string ChecksumsSha256 = getDscHash(DoHashes, Hashes::SHA256SUM, Tags, "Checksums-Sha256", Db.HashesList.find("SHA256"), St.st_size, strippedName);
+   std::string ChecksumsSha512 = getDscHash(DoHashes, Hashes::SHA512SUM, Tags, "Checksums-Sha512", Db.HashesList.find("SHA512"), St.st_size, strippedName);
 
    // Strip the DirStrip prefix from the FileName and add the PathPrefix
    string NewFileName;
@@ -752,7 +746,7 @@ bool SourcesWriter::DoPackage(string FileName)
    char *RealPath = NULL;
    for (;isspace(*C); C++);
    while (*C != 0)
-   {   
+   {
       // Parse each of the elements
       if (ParseQuoteWord(C,ParseJnk) == false ||
          ParseQuoteWord(C,ParseJnk) == false ||
@@ -782,21 +776,21 @@ bool SourcesWriter::DoPackage(string FileName)
            if (hs->HashType() == "MD5Sum" || hs->HashType() == "Checksum-FileSize")
               continue;
            char const * fieldname;
-           std::ostream * out;
+           std::string * out;
            if (hs->HashType() == "SHA1")
            {
               fieldname = "Checksums-Sha1";
-              out = &ostreamSha1;
+              out = &ChecksumsSha1;
            }
            else if (hs->HashType() == "SHA256")
            {
               fieldname = "Checksums-Sha256";
-              out = &ostreamSha256;
+              out = &ChecksumsSha256;
            }
            else if (hs->HashType() == "SHA512")
            {
               fieldname = "Checksums-Sha512";
-              out = &ostreamSha512;
+              out = &ChecksumsSha512;
            }
            else
            {
@@ -805,10 +799,12 @@ bool SourcesWriter::DoPackage(string FileName)
            }
            if (Tags.Exists(fieldname) == true)
               continue;
-           (*out) << "\n " << hs->HashValue() << " " << Db.GetFileSize() << " " << ParseJnk;
+           std::ostringstream streamout;
+           streamout << "\n " << hs->HashValue() << " " << Db.GetFileSize() << " " << ParseJnk;
+           out->append(streamout.str());
         }
 
-        // write back the GetFileInfo() stats data 
+        // write back the GetFileInfo() stats data
         Db.Finish();
       }
 
@@ -829,53 +825,48 @@ 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)
-   std::vector<TFRewriteData> Changes;
+   std::vector<pkgTagSection::Tag> Changes;
 
-   Changes.push_back(SetTFRewriteData("Source",Package.c_str(),"Package"));
+   Changes.push_back(pkgTagSection::Tag::Remove("Source"));
+   Changes.push_back(pkgTagSection::Tag::Rewrite("Package", Package));
    if (Files.empty() == false)
-      Changes.push_back(SetTFRewriteData("Files",Files.c_str()));
+      Changes.push_back(pkgTagSection::Tag::Rewrite("Files", Files));
    if (ChecksumsSha1.empty() == false)
-      Changes.push_back(SetTFRewriteData("Checksums-Sha1",ChecksumsSha1.c_str()));
+      Changes.push_back(pkgTagSection::Tag::Rewrite("Checksums-Sha1", ChecksumsSha1));
    if (ChecksumsSha256.empty() == false)
-      Changes.push_back(SetTFRewriteData("Checksums-Sha256",ChecksumsSha256.c_str()));
+      Changes.push_back(pkgTagSection::Tag::Rewrite("Checksums-Sha256", ChecksumsSha256));
    if (ChecksumsSha512.empty() == false)
-      Changes.push_back(SetTFRewriteData("Checksums-Sha512",ChecksumsSha512.c_str()));
+      Changes.push_back(pkgTagSection::Tag::Rewrite("Checksums-Sha512", ChecksumsSha512));
    if (Directory != "./")
-      Changes.push_back(SetTFRewriteData("Directory",Directory.c_str()));
-   Changes.push_back(SetTFRewriteData("Priority",BestPrio.c_str()));
-   Changes.push_back(SetTFRewriteData("Status",0));
+      Changes.push_back(pkgTagSection::Tag::Rewrite("Directory", Directory));
+   Changes.push_back(pkgTagSection::Tag::Rewrite("Priority", BestPrio));
+   Changes.push_back(pkgTagSection::Tag::Remove("Status"));
 
    // Rewrite the maintainer field if necessary
    bool MaintFailed;
-   string NewMaint = OverItem->SwapMaint(Tags.FindS("Maintainer"),MaintFailed);
+   string NewMaint = OverItem->SwapMaint(Tags.FindS("Maintainer"), MaintFailed);
    if (MaintFailed == true)
    {
       if (NoOverride == false)
       {
-        NewLine(1);     
+        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)
-      Changes.push_back(SetTFRewriteData("Maintainer", NewMaint.c_str()));
-   
-   for (map<string,string>::const_iterator I = SOverItem->FieldOverride.begin(); 
+      Changes.push_back(pkgTagSection::Tag::Rewrite("Maintainer", NewMaint.c_str()));
+
+   for (map<string,string>::const_iterator I = SOverItem->FieldOverride.begin();
         I != SOverItem->FieldOverride.end(); ++I)
-      Changes.push_back(SetTFRewriteData(I->first.c_str(),I->second.c_str()));
+      Changes.push_back(pkgTagSection::Tag::Rewrite(I->first, I->second));
 
-   Changes.push_back(SetTFRewriteData(0, 0));
-      
    // Rewrite and store the fields.
-   if (TFRewrite(Output,Tags,TFRewriteSourceOrder,Changes.data()) == false)
+   if (Tags.Write(*Output, TFRewriteSourceOrder, Changes) == false ||
+        Output->Write("\n", 1) == false)
       return false;
-   fprintf(Output,"\n");
 
    Stats.Packages++;
    
@@ -886,12 +877,11 @@ bool SourcesWriter::DoPackage(string FileName)
 // ContentsWriter::ContentsWriter - Constructor                                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-ContentsWriter::ContentsWriter(string const &DB, string const &Arch) :
-                   FTWScanner(Arch), Db(DB), Stats(Db.Stats)
+ContentsWriter::ContentsWriter(FileFd * const GivenOutput, string const &DB, string const &Arch) :
+                   FTWScanner(GivenOutput, Arch), Db(DB), Stats(Db.Stats)
 
 {
    SetExts(".deb");
-   Output = stdout;
 }
                                                                        /*}}}*/
 // ContentsWriter::DoPackage - Process a single package                        /*{{{*/
@@ -973,7 +963,7 @@ bool ContentsWriter::ReadFromPkgs(string const &PkgFile,string const &PkgCompres
 // ReleaseWriter::ReleaseWriter - Constructor                          /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-ReleaseWriter::ReleaseWriter(string const &/*DB*/)
+ReleaseWriter::ReleaseWriter(FileFd * const GivenOutput, string const &/*DB*/) : FTWScanner(GivenOutput)
 {
    if (_config->FindB("APT::FTPArchive::Release::Default-Patterns", true) == true)
    {
@@ -995,7 +985,6 @@ ReleaseWriter::ReleaseWriter(string const &/*DB*/)
    }
    AddPatterns(_config->FindVector("APT::FTPArchive::Release::Patterns"));
 
-   Output = stdout;
    time_t const now = time(NULL);
 
    setlocale(LC_TIME, "C");
@@ -1039,7 +1028,8 @@ ReleaseWriter::ReleaseWriter(string const &/*DB*/)
       if (Value == "")
          continue;
 
-      fprintf(Output, "%s: %s\n", (*I).first.c_str(), Value.c_str());
+      std::string const out = I->first + ": " + Value + "\n";
+      Output->Write(out.c_str(), out.length());
    }
 
    ConfigToDoHashes(DoHashes, "APT::FTPArchive::Release");
@@ -1075,8 +1065,8 @@ bool ReleaseWriter::DoPackage(string FileName)
 
    CheckSums[NewFileName].size = fd.Size();
 
-   Hashes hs;
-   hs.AddFD(fd, 0, DoHashes);
+   Hashes hs(DoHashes);
+   hs.AddFD(fd);
    CheckSums[NewFileName].Hashes = hs.GetHashStringList();
    fd.Close();
 
@@ -1086,29 +1076,35 @@ bool ReleaseWriter::DoPackage(string FileName)
                                                                        /*}}}*/
 // ReleaseWriter::Finish - Output the checksums                                /*{{{*/
 // ---------------------------------------------------------------------
-static void printChecksumTypeRecord(FILE * const Output, char const * const Type, map<string, ReleaseWriter::CheckSum> const &CheckSums)
+static void printChecksumTypeRecord(FileFd &Output, char const * const Type, map<string, ReleaseWriter::CheckSum> const &CheckSums)
 {
-      fprintf(Output, "%s:\n", Type);
-      for(map<string,ReleaseWriter::CheckSum>::const_iterator I = CheckSums.begin();
-         I != CheckSums.end(); ++I)
-      {
-        HashString const * const hs = I->second.Hashes.find(Type);
-        if (hs == NULL)
-           continue;
-        fprintf(Output, " %s %16llu %s\n",
-                hs->HashValue().c_str(),
-                (*I).second.size,
-                (*I).first.c_str());
-      }
+   {
+      std::string out;
+      strprintf(out, "%s:\n", Type);
+      Output.Write(out.c_str(), out.length());
+   }
+   for(map<string,ReleaseWriter::CheckSum>::const_iterator I = CheckSums.begin();
+        I != CheckSums.end(); ++I)
+   {
+      HashString const * const hs = I->second.Hashes.find(Type);
+      if (hs == NULL)
+        continue;
+      std::string out;
+      strprintf(out, " %s %16llu %s\n",
+           hs->HashValue().c_str(),
+           (*I).second.size,
+           (*I).first.c_str());
+      Output.Write(out.c_str(), out.length());
+   }
 }
 void ReleaseWriter::Finish()
 {
    if ((DoHashes & Hashes::MD5SUM) == Hashes::MD5SUM)
-      printChecksumTypeRecord(Output, "MD5Sum", CheckSums);
+      printChecksumTypeRecord(*Output, "MD5Sum", CheckSums);
    if ((DoHashes & Hashes::SHA1SUM) == Hashes::SHA1SUM)
-      printChecksumTypeRecord(Output, "SHA1", CheckSums);
+      printChecksumTypeRecord(*Output, "SHA1", CheckSums);
    if ((DoHashes & Hashes::SHA256SUM) == Hashes::SHA256SUM)
-      printChecksumTypeRecord(Output, "SHA256", CheckSums);
+      printChecksumTypeRecord(*Output, "SHA256", CheckSums);
    if ((DoHashes & Hashes::SHA512SUM) == Hashes::SHA512SUM)
-      printChecksumTypeRecord(Output, "SHA512", CheckSums);
+      printChecksumTypeRecord(*Output, "SHA512", CheckSums);
 }