]> git.saurik.com Git - apt.git/blobdiff - ftparchive/writer.cc
merged from apt-get-changelog
[apt.git] / ftparchive / writer.cc
index 5547c6aa5175faa3312f4dcf72461b872d1fa3f3..d7d699ddc8a0e63bc7948b8da278e7fa66862e50 100644 (file)
@@ -28,6 +28,7 @@
 #include <ftw.h>
 #include <fnmatch.h>
 #include <iostream>
+#include <sstream>
 #include <memory>
     
 #include "cachedb.h"
@@ -54,14 +55,10 @@ inline void SetTFRewriteData(struct TFRewriteData &tfrd,
 // FTWScanner::FTWScanner - Constructor                                        /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-FTWScanner::FTWScanner()
+FTWScanner::FTWScanner(string const &Arch): Arch(Arch)
 {
    ErrorPrinted = false;
    NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true);
-   RealPath = 0;
-   long PMax = pathconf(".",_PC_PATH_MAX);
-   if (PMax > 0)
-      RealPath = new char[PMax];
 }
                                                                        /*}}}*/
 // FTWScanner::Scanner - FTW Scanner                                   /*{{{*/
@@ -92,6 +89,8 @@ int FTWScanner::ScannerFTW(const char *File,const struct stat *sb,int Flag)
 int FTWScanner::ScannerFile(const char *File, bool const &ReadLink)
 {
    const char *LastComponent = strrchr(File, '/');
+   char *RealPath = NULL;
+
    if (LastComponent == NULL)
       LastComponent = File;
    else
@@ -111,10 +110,13 @@ int FTWScanner::ScannerFile(const char *File, bool const &ReadLink)
       given are not links themselves. */
    char Jnk[2];
    Owner->OriginalPath = File;
-   if (ReadLink && Owner->RealPath != 0 &&
+   if (ReadLink &&
        readlink(File,Jnk,sizeof(Jnk)) != -1 &&
-       realpath(File,Owner->RealPath) != 0)
-      Owner->DoPackage(Owner->RealPath);
+       (RealPath = realpath(File,NULL)) != 0)
+   {
+      Owner->DoPackage(RealPath);
+      free(RealPath);
+   }
    else
       Owner->DoPackage(File);
    
@@ -150,13 +152,15 @@ int FTWScanner::ScannerFile(const char *File, bool const &ReadLink)
 /* */
 bool FTWScanner::RecursiveScan(string const &Dir)
 {
+   char *RealPath = NULL;
    /* If noprefix is set then jam the scan root in, so we don't generate
       link followed paths out of control */
    if (InternalPrefix.empty() == true)
    {
-      if (realpath(Dir.c_str(),RealPath) == 0)
+      if ((RealPath = realpath(Dir.c_str(),NULL)) == 0)
         return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str());
-      InternalPrefix = RealPath;      
+      InternalPrefix = RealPath;
+      free(RealPath);
    }
    
    // Do recursive directory searching
@@ -180,13 +184,15 @@ bool FTWScanner::RecursiveScan(string const &Dir)
    of files from another file. */
 bool FTWScanner::LoadFileList(string const &Dir, string const &File)
 {
+   char *RealPath = NULL;
    /* If noprefix is set then jam the scan root in, so we don't generate
       link followed paths out of control */
    if (InternalPrefix.empty() == true)
    {
-      if (realpath(Dir.c_str(),RealPath) == 0)
+      if ((RealPath = realpath(Dir.c_str(),NULL)) == 0)
         return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str());
       InternalPrefix = RealPath;      
+      free(RealPath);
    }
    
    Owner = this;
@@ -294,12 +300,11 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
 // ---------------------------------------------------------------------
 /* */
 PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string const &ExtOverrides,
-                              string const &aArch) :
-   Db(DB),Stats(Db.Stats), Arch(aArch)
+                              string const &Arch) :
+   FTWScanner(Arch), Db(DB), Stats(Db.Stats), TransWriter(NULL)
 {
    Output = stdout;
-   SetExts(".deb .udeb .foo .bar .baz");
-   AddPattern("*.deb");
+   SetExts(".deb .udeb");
    DeLinkLimit = 0;
    
    // Process the command line options
@@ -313,7 +318,7 @@ PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string c
 
    if (Db.Loaded() == false)
       DoContents = false;
-      
+
    // Read the override file
    if (Overrides.empty() == false && Over.ReadOverride(Overrides) == false)
       return;
@@ -335,17 +340,16 @@ bool FTWScanner::SetExts(string const &Vals)
    string::size_type Start = 0;
    while (Start <= Vals.length()-1)
    {
-      string::size_type Space = Vals.find(' ',Start);
-      string::size_type Length;
-      if (Space == string::npos)
+      string::size_type const Space = Vals.find(' ',Start);
+      string::size_type const Length = ((Space == string::npos) ? Vals.length() : Space) - Start;
+      if ( Arch.empty() == false )
       {
-         Length = Vals.length()-Start;
+        AddPattern(string("*_") + Arch + Vals.substr(Start, Length));
+        AddPattern(string("*_all") + Vals.substr(Start, Length));
       }
       else
-      {
-         Length = Space-Start;
-      }
-      AddPattern(string("*") + Vals.substr(Start, Length));
+        AddPattern(string("*") + Vals.substr(Start, Length));
+
       Start += Length + 1;
    }
 
@@ -445,6 +449,8 @@ bool PackagesWriter::DoPackage(string FileName)
       descmd5.Add(desc.c_str());
       DescriptionMd5 = descmd5.Result().Value();
       SetTFRewriteData(Changes[End++], "Description-md5", DescriptionMd5.c_str());
+      if (TransWriter != NULL)
+        TransWriter->DoPackage(Package, desc, DescriptionMd5);
    }
 
    // Rewrite the maintainer field if necessary
@@ -491,6 +497,55 @@ bool PackagesWriter::DoPackage(string FileName)
 }
                                                                        /*}}}*/
 
+// 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)
+{
+   if (File.empty() == true)
+      return;
+
+   Comp = new MultiCompress(File, TransCompress, Permissions);
+   Output = Comp->Input;
+}
+                                                                       /*}}}*/
+// TranslationWriter::DoPackage - Process a single package             /*{{{*/
+// ---------------------------------------------------------------------
+/* Create a Translation-Master file for this Packages file */
+bool TranslationWriter::DoPackage(string const &Pkg, string const &Desc,
+                                 string const &MD5)
+{
+   if (Output == NULL)
+      return true;
+
+   // Different archs can include different versions and therefore
+   // different descriptions - so we need to check for both name and md5.
+   string const Record = Pkg + ":" + MD5;
+
+   if (Included.find(Record) != Included.end())
+      return true;
+
+   fprintf(Output, "Package: %s\nDescription-md5: %s\nDescription-en: %s\n",
+          Pkg.c_str(), MD5.c_str(), Desc.c_str());
+
+   Included.insert(Record);
+   return true;
+}
+                                                                       /*}}}*/
+// TranslationWriter::~TranslationWriter - Destructor                  /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+TranslationWriter::~TranslationWriter()
+{
+   if (Comp == NULL)
+      return;
+
+   delete Comp;
+}
+                                                                       /*}}}*/
+
 // SourcesWriter::SourcesWriter - Constructor                          /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -555,7 +610,12 @@ bool SourcesWriter::DoPackage(string FileName)
    char *BlkEnd = Buffer + St.st_size;
    MD5Summation MD5;
    MD5.Add((unsigned char *)Start,BlkEnd - Start);
-      
+
+   SHA1Summation SHA1;
+   SHA256Summation SHA256;
+   SHA1.Add((unsigned char *)Start,BlkEnd - Start);
+   SHA256.Add((unsigned char *)Start,BlkEnd - Start);
+
    // Add an extra \n to the end, just in case
    *BlkEnd++ = '\n';
    
@@ -646,12 +706,25 @@ bool SourcesWriter::DoPackage(string FileName)
    }
    
    // Add the dsc to the files hash list
-   char Files[1000];
-   snprintf(Files,sizeof(Files),"\n %s %lu %s\n %s",
-           string(MD5.Result()).c_str(),St.st_size,
-           flNotDir(FileName).c_str(),
-           Tags.FindS("Files").c_str());
-   
+   string const strippedName = flNotDir(FileName);
+   std::ostringstream ostreamFiles;
+   if (Tags.Exists("Files"))
+      ostreamFiles << "\n " << string(MD5.Result()) << " " << St.st_size << " "
+                  << strippedName << "\n " << Tags.FindS("Files");
+   string const Files = ostreamFiles.str();
+
+   std::ostringstream ostreamSha1;
+   if (Tags.Exists("Checksums-Sha1"))
+      ostreamSha1 << "\n " << string(SHA1.Result()) << " " << St.st_size << " "
+                  << strippedName << "\n " << Tags.FindS("Checksums-Sha1");
+   string const ChecksumsSha1 = ostreamSha1.str();
+
+   std::ostringstream ostreamSha256;
+   if (Tags.Exists("Checksums-Sha256"))
+      ostreamSha256 << "\n " << string(SHA256.Result()) << " " << St.st_size << " "
+                  << strippedName << "\n " << Tags.FindS("Checksums-Sha256");
+   string const ChecksumsSha256 = ostreamSha256.str();
+
    // Strip the DirStrip prefix from the FileName and add the PathPrefix
    string NewFileName;
    if (DirStrip.empty() == false &&
@@ -668,7 +741,8 @@ bool SourcesWriter::DoPackage(string FileName)
 
    // Perform the delinking operation over all of the files
    string ParseJnk;
-   const char *C = Files;
+   const char *C = Files.c_str();
+   char *RealPath = NULL;
    for (;isspace(*C); C++);
    while (*C != 0)
    {   
@@ -680,10 +754,11 @@ bool SourcesWriter::DoPackage(string FileName)
       
       char Jnk[2];
       string OriginalPath = Directory + ParseJnk;
-      if (RealPath != 0 && readlink(OriginalPath.c_str(),Jnk,sizeof(Jnk)) != -1 &&
-         realpath(OriginalPath.c_str(),RealPath) != 0)
+      if (readlink(OriginalPath.c_str(),Jnk,sizeof(Jnk)) != -1 &&
+         (RealPath = realpath(OriginalPath.c_str(),NULL)) != 0)
       {
         string RP = RealPath;
+        free(RealPath);
         if (Delink(RP,OriginalPath.c_str(),Stats.DeLinkBytes,St.st_size) == false)
            return false;
       }
@@ -694,12 +769,14 @@ bool SourcesWriter::DoPackage(string FileName)
       Directory.erase(Directory.end()-1);
 
    // This lists all the changes to the fields we are going to make.
-   // (5 hardcoded + maintainer + end marker)
-   TFRewriteData Changes[5+1+SOverItem->FieldOverride.size()+1];
+   // (5 hardcoded + checksums + maintainer + end marker)
+   TFRewriteData Changes[5+2+1+SOverItem->FieldOverride.size()+1];
 
    unsigned int End = 0;
    SetTFRewriteData(Changes[End++],"Source",Package.c_str(),"Package");
-   SetTFRewriteData(Changes[End++],"Files",Files);
+   SetTFRewriteData(Changes[End++],"Files",Files.c_str());
+   SetTFRewriteData(Changes[End++],"Checksums-Sha1",ChecksumsSha1.c_str());
+   SetTFRewriteData(Changes[End++],"Checksums-Sha256",ChecksumsSha256.c_str());
    if (Directory != "./")
       SetTFRewriteData(Changes[End++],"Directory",Directory.c_str());
    SetTFRewriteData(Changes[End++],"Priority",BestPrio.c_str());
@@ -740,11 +817,11 @@ bool SourcesWriter::DoPackage(string FileName)
 // ContentsWriter::ContentsWriter - Constructor                                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-ContentsWriter::ContentsWriter(string const &DB) : 
-                   Db(DB), Stats(Db.Stats)
+ContentsWriter::ContentsWriter(string const &DB, string const &Arch) :
+                   FTWScanner(Arch), Db(DB), Stats(Db.Stats)
 
 {
-   AddPattern("*.deb");
+   SetExts(".deb");
    Output = stdout;
 }
                                                                        /*}}}*/
@@ -850,6 +927,15 @@ ReleaseWriter::ReleaseWriter(string const &DB)
       datestr[0] = '\0';
    }
 
+   time_t const validuntil = now + _config->FindI("APT::FTPArchive::Release::ValidTime", 0);
+   char validstr[128];
+   if (now == validuntil ||
+       strftime(validstr, sizeof(validstr), "%a, %d %b %Y %H:%M:%S UTC",
+                gmtime(&validuntil)) == 0)
+   {
+      validstr[0] = '\0';
+   }
+
    map<string,string> Fields;
    Fields["Origin"] = "";
    Fields["Label"] = "";
@@ -857,6 +943,7 @@ ReleaseWriter::ReleaseWriter(string const &DB)
    Fields["Version"] = "";
    Fields["Codename"] = "";
    Fields["Date"] = datestr;
+   Fields["Valid-Until"] = validstr;
    Fields["Architectures"] = "";
    Fields["Components"] = "";
    Fields["Description"] = "";