]> git.saurik.com Git - apt.git/blobdiff - ftparchive/writer.cc
Fix typo in apt-get.cc and update PO files
[apt.git] / ftparchive / writer.cc
index a4877d635d3e5f4f0e1addbaab5961bf7091e083..fc9ea27d7e52af22d10f5a8d8b46e6c21edead2e 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: writer.cc,v 1.4 2001/06/26 02:50:27 jgg Exp $
+// $Id: writer.cc,v 1.14 2004/03/24 01:40:43 mdz Exp $
 /* ######################################################################
 
    Writer 
 
 #include "writer.h"
     
+#include <apti18n.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/md5.h>
+#include <apt-pkg/sha1.h>
 #include <apt-pkg/deblistparser.h>
 
 #include <sys/types.h>
 #include <unistd.h>
+#include <ctime>
 #include <ftw.h>
+#include <fnmatch.h>
 #include <iostream>
     
 #include "cachedb.h"
 #include "apt-ftparchive.h"
 #include "multicompress.h"
                                                                        /*}}}*/
-
 using namespace std;
 FTWScanner *FTWScanner::Owner;
 
@@ -57,8 +60,6 @@ FTWScanner::FTWScanner()
 {
    ErrorPrinted = false;
    NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true);
-   TmpExt = 0;
-   Ext[0] = 0;
    RealPath = 0;
    long PMax = pathconf(".",_PC_PATH_MAX);
    if (PMax > 0)
@@ -74,26 +75,29 @@ int FTWScanner::Scanner(const char *File,const struct stat *sb,int Flag)
    if (Flag == FTW_DNR)
    {
       Owner->NewLine(1);
-      c1out << "W: Unable to read directory " << File << endl;
+      ioprintf(c1out, _("W: Unable to read directory %s\n"), File);
    }   
    if (Flag == FTW_NS)
    {
       Owner->NewLine(1);
-      c1out << "W: Unable to stat " << File << endl;
+      ioprintf(c1out, _("W: Unable to stat %s\n"), File);
    }   
    if (Flag != FTW_F)
       return 0;
 
-   // See if it is a .deb
-   if (strlen(File) < 4)
-      return 0;
-   
-   unsigned CurExt = 0;
-   for (; Owner->Ext[CurExt] != 0; CurExt++)
-      if (strcmp(File+strlen(File)-strlen(Owner->Ext[CurExt]),
-                Owner->Ext[CurExt]) == 0)
-        break;
-   if (Owner->Ext[CurExt] == 0)
+   const char *LastComponent = strrchr(File, '/');
+   if (LastComponent == NULL)
+      LastComponent = File;
+   else
+      LastComponent++;
+
+   vector<string>::iterator I;
+   for(I = Owner->Patterns.begin(); I != Owner->Patterns.end(); ++I)
+   {
+      if (fnmatch((*I).c_str(), LastComponent, 0) == 0)
+         break;
+   }
+   if (I == Owner->Patterns.end())
       return 0;
 
    /* Process it. If the file is a link then resolve it into an absolute
@@ -118,16 +122,16 @@ int FTWScanner::Scanner(const char *File,const struct stat *sb,int Flag)
         
         bool Type = _error->PopMessage(Err);
         if (Type == true)
-           c1out << "E: " << Err << endl;
+           cerr << _("E: ") << Err << endl;
         else
-           c1out << "W: " << Err << endl;
+           cerr << _("W: ") << Err << endl;
         
         if (Err.find(File) != string::npos)
            SeenPath = true;
       }      
       
       if (SeenPath == false)
-        cerr << "E: Errors apply to file '" << File << "'" << endl;
+        cerr << _("E: Errors apply to file ") << "'" << File << "'" << endl;
       return 0;
    }
    
@@ -144,7 +148,7 @@ bool FTWScanner::RecursiveScan(string Dir)
    if (InternalPrefix.empty() == true)
    {
       if (realpath(Dir.c_str(),RealPath) == 0)
-        return _error->Errno("realpath","Failed to resolve %s",Dir.c_str());
+        return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str());
       InternalPrefix = RealPath;      
    }
    
@@ -156,7 +160,7 @@ bool FTWScanner::RecursiveScan(string Dir)
    if (Res != 0)
    {
       if (_error->PendingError() == false)
-        _error->Errno("ftw","Tree walking failed");
+        _error->Errno("ftw",_("Tree walking failed"));
       return false;
    }
    
@@ -174,14 +178,14 @@ bool FTWScanner::LoadFileList(string Dir,string File)
    if (InternalPrefix.empty() == true)
    {
       if (realpath(Dir.c_str(),RealPath) == 0)
-        return _error->Errno("realpath","Failed to resolve %s",Dir.c_str());
+        return _error->Errno("realpath",_("Failed to resolve %s"),Dir.c_str());
       InternalPrefix = RealPath;      
    }
    
    Owner = this;
    FILE *List = fopen(File.c_str(),"r");
    if (List == 0)
-      return _error->Errno("fopen","Failed to open %s",File.c_str());
+      return _error->Errno("fopen",_("Failed to open %s"),File.c_str());
    
    /* We are a tad tricky here.. We prefix the buffer with the directory
       name, that way if we need a full path with just use line.. Sneaky and
@@ -238,25 +242,26 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
            cout << endl;
         
         NewLine(1);
-        c1out << " DeLink " << (OriginalPath + InternalPrefix.length())
-           << " [" << SizeToStr(St.st_size) << "B]" << endl << flush;
+        ioprintf(c1out, _(" DeLink %s [%s]\n"), (OriginalPath + InternalPrefix.length()),
+                   SizeToStr(St.st_size).c_str());
+        c1out << flush;
         
         if (NoLinkAct == false)
         {
            char OldLink[400];
            if (readlink(OriginalPath,OldLink,sizeof(OldLink)) == -1)
-              _error->Errno("readlink","Failed to readlink %s",OriginalPath);
+              _error->Errno("readlink",_("Failed to readlink %s"),OriginalPath);
            else
            {
               if (unlink(OriginalPath) != 0)
-                 _error->Errno("unlink","Failed to unlink %s",OriginalPath);
+                 _error->Errno("unlink",_("Failed to unlink %s"),OriginalPath);
               else
               {
                  if (link(FileName.c_str(),OriginalPath) != 0)
                  {
                     // Panic! Restore the symlink
                     symlink(OldLink,OriginalPath);
-                    return _error->Errno("link","*** Failed to link %s to %s",
+                    return _error->Errno("link",_("*** Failed to link %s to %s"),
                                          FileName.c_str(),
                                          OriginalPath);
                  }            
@@ -266,7 +271,7 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
         
         DeLinkBytes += St.st_size;
         if (DeLinkBytes/1024 >= DeLinkLimit)
-           c1out << " DeLink limit of " << SizeToStr(DeLinkBytes) << "B hit." << endl;      
+           ioprintf(c1out, _(" DeLink limit of %sB hit.\n"), SizeToStr(DeLinkBytes).c_str());      
       }
       
       FileName = OriginalPath;
@@ -275,27 +280,17 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
    return true;
 }
                                                                        /*}}}*/
-// FTWScanner::SetExts - Set extensions to support                     /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool FTWScanner::SetExts(string Vals)
-{
-   delete [] TmpExt;
-   TmpExt = new char[Vals.length()+1];
-   strcpy(TmpExt,Vals.c_str());
-   return TokSplitString(' ',TmpExt,(char **)Ext,sizeof(Ext)/sizeof(Ext[0]));
-}
-                                                                       /*}}}*/
 
 // PackagesWriter::PackagesWriter - Constructor                                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-PackagesWriter::PackagesWriter(string DB,string Overrides,string ExtOverrides) :
-                   Db(DB),Stats(Db.Stats)
+PackagesWriter::PackagesWriter(string DB,string Overrides,string ExtOverrides,
+                              string aArch) :
+   Db(DB),Stats(Db.Stats), Arch(aArch)
 {
    Output = stdout;
-   Ext[0] = ".deb";
-   Ext[1] = 0;
+   SetExts(".deb .udeb .foo .bar .baz");
+   AddPattern("*.deb");
    DeLinkLimit = 0;
    
    // Process the command line options
@@ -317,6 +312,33 @@ PackagesWriter::PackagesWriter(string DB,string Overrides,string ExtOverrides) :
 
    _error->DumpErrors();
 }
+                                                                        /*}}}*/
+// FTWScanner::SetExts - Set extensions to support                      /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool FTWScanner::SetExts(string Vals)
+{
+   ClearPatterns();
+   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)
+      {
+         Length = Vals.length()-Start;
+      }
+      else
+      {
+         Length = Space-Start;
+      }
+      AddPattern(string("*") + Vals.substr(Start, Length));
+      Start += Length + 1;
+   }
+
+   return true;
+}
+
                                                                        /*}}}*/
 // PackagesWriter::DoPackage - Process a single package                        /*{{{*/
 // ---------------------------------------------------------------------
@@ -333,7 +355,7 @@ bool PackagesWriter::DoPackage(string FileName)
    // 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());
+      return _error->Errno("fstat",_("Failed to stat %s"),FileName.c_str());
 
    // Pull all the data we need form the DB
    string MD5Res;
@@ -349,24 +371,32 @@ bool PackagesWriter::DoPackage(string FileName)
    // Lookup the overide information
    pkgTagSection &Tags = Db.Control.Section;
    string Package = Tags.FindS("Package");
-   Override::Item Tmp;
-   Override::Item *OverItem = Over.GetItem(Package);
+   string Architecture;
+   // if we generate a Packages file for a given arch, we use it to
+   // look for overrides. if we run in "simple" mode without the 
+   // "Architecures" variable in the config we use the architecure value
+   // from the deb file
+   if(Arch != "")
+      Architecture = Arch;
+   else
+      Architecture = Tags.FindS("Architecture");
+   auto_ptr<Override::Item> OverItem(Over.GetItem(Package,Architecture));
    
    if (Package.empty() == true)
-      return _error->Error("Archive had no package field");
-   
+      return _error->Error(_("Archive had no package field"));
+
    // If we need to do any rewriting of the header do it now..
-   if (OverItem == 0)
+   if (OverItem.get() == 0)
    {
       if (NoOverride == false)
       {
         NewLine(1);
-        c1out << "  " << Package << " has no override entry" << endl;
+        ioprintf(c1out, _("  %s has no override entry\n"), Package.c_str());
       }
       
-      OverItem = &Tmp;
-      Tmp.FieldOverride["Section"] = Tags.FindS("Section");
-      Tmp.Priority = Tags.FindS("Priority");
+      OverItem = auto_ptr<Override::Item>(new Override::Item);
+      OverItem->FieldOverride["Section"] = Tags.FindS("Section");
+      OverItem->Priority = Tags.FindS("Priority");
    }
 
    char Size[40];
@@ -404,9 +434,8 @@ bool PackagesWriter::DoPackage(string FileName)
       if (NoOverride == false)
       {
         NewLine(1);
-        c1out << "  " << Package << " maintainer is " <<
-              Tags.FindS("Maintainer") << " not " <<
-              OverItem->OldMaint << endl;
+        ioprintf(c1out, _("  %s maintainer is %s not %s\n"),
+              Package.c_str(), Tags.FindS("Maintainer").c_str(), OverItem->OldMaint.c_str());
       }      
    }
    
@@ -448,8 +477,7 @@ SourcesWriter::SourcesWriter(string BOverrides,string SOverrides,
                             string ExtOverrides)
 {
    Output = stdout;
-   Ext[0] = ".dsc";
-   Ext[1] = 0;
+   AddPattern("*.dsc");
    DeLinkLimit = 0;
    Buffer = 0;
    BufSize = 0;
@@ -535,10 +563,10 @@ bool SourcesWriter::DoPackage(string FileName)
       
    // Lookup the overide information, finding first the best priority.
    string BestPrio;
-   char Buffer[1000];
    string Bins = Tags.FindS("Binary");
-   Override::Item *OverItem = 0;
-   if (Bins.empty() == false && Bins.length() < sizeof(Buffer))
+   char Buffer[Bins.length() + 1];
+   auto_ptr<Override::Item> OverItem(0);
+   if (Bins.empty() == false)
    {
       strcpy(Buffer,Bins.c_str());
       
@@ -550,11 +578,9 @@ bool SourcesWriter::DoPackage(string FileName)
       unsigned char BestPrioV = pkgCache::State::Extra;
       for (unsigned I = 0; BinList[I] != 0; I++)
       {
-        Override::Item *Itm = BOver.GetItem(BinList[I]);
-        if (Itm == 0)
+        auto_ptr<Override::Item> Itm(BOver.GetItem(BinList[I]));
+        if (Itm.get() == 0)
            continue;
-        if (OverItem == 0)
-           OverItem = Itm;
 
         unsigned char NewPrioV = debListParser::GetPrio(Itm->Priority);
         if (NewPrioV < BestPrioV || BestPrio.empty() == true)
@@ -562,28 +588,34 @@ bool SourcesWriter::DoPackage(string FileName)
            BestPrioV = NewPrioV;
            BestPrio = Itm->Priority;
         }       
+
+        if (OverItem.get() == 0)
+           OverItem = Itm;
       }
    }
    
    // If we need to do any rewriting of the header do it now..
-   Override::Item Tmp;   
-   if (OverItem == 0)
+   if (OverItem.get() == 0)
    {
       if (NoOverride == false)
       {
         NewLine(1);     
-        c1out << "  " << Tags.FindS("Source") << " has no override entry" << endl;
+        ioprintf(c1out, _("  %s has no override entry\n"), Tags.FindS("Source").c_str());
       }
       
-      OverItem = &Tmp;
+      OverItem = auto_ptr<Override::Item>(new Override::Item);
    }
    
-   Override::Item *SOverItem = SOver.GetItem(Tags.FindS("Source"));
-   if (SOverItem == 0)
+   auto_ptr<Override::Item> SOverItem(SOver.GetItem(Tags.FindS("Source")));
+   const auto_ptr<Override::Item> autoSOverItem(SOverItem);
+   if (SOverItem.get() == 0)
    {
-      SOverItem = BOver.GetItem(Tags.FindS("Source"));
-      if (SOverItem == 0)
-        SOverItem = OverItem;
+      SOverItem = auto_ptr<Override::Item>(BOver.GetItem(Tags.FindS("Source")));
+      if (SOverItem.get() == 0)
+      {
+        SOverItem = auto_ptr<Override::Item>(new Override::Item);
+        *SOverItem = *OverItem;
+      }
    }
    
    // Add the dsc to the files hash list
@@ -603,10 +635,10 @@ bool SourcesWriter::DoPackage(string FileName)
       NewFileName = OriginalPath;
    if (PathPrefix.empty() == false)
       NewFileName = flCombine(PathPrefix,NewFileName);
-    
+
    string Directory = flNotFile(OriginalPath);
    string Package = Tags.FindS("Source");
-   
+
    // Perform the delinking operation over all of the files
    string ParseJnk;
    const char *C = Files;
@@ -633,7 +665,7 @@ bool SourcesWriter::DoPackage(string FileName)
    Directory = flNotFile(NewFileName);
    if (Directory.length() > 2)
       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];
@@ -641,7 +673,8 @@ bool SourcesWriter::DoPackage(string FileName)
    unsigned int End = 0;
    SetTFRewriteData(Changes[End++],"Source",Package.c_str(),"Package");
    SetTFRewriteData(Changes[End++],"Files",Files);
-   SetTFRewriteData(Changes[End++],"Directory",Directory.c_str());
+   if (Directory != "./")
+      SetTFRewriteData(Changes[End++],"Directory",Directory.c_str());
    SetTFRewriteData(Changes[End++],"Priority",BestPrio.c_str());
    SetTFRewriteData(Changes[End++],"Status",0);
 
@@ -653,9 +686,8 @@ bool SourcesWriter::DoPackage(string FileName)
       if (NoOverride == false)
       {
         NewLine(1);     
-        c1out << "  " << Package << " maintainer is " <<
-              Tags.FindS("Maintainer") << " not " <<
-              OverItem->OldMaint << endl;
+        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)
@@ -685,8 +717,7 @@ ContentsWriter::ContentsWriter(string DB) :
                    Db(DB), Stats(Db.Stats)
 
 {
-   Ext[0] = ".deb";
-   Ext[1] = 0;
+   AddPattern("*.deb");
    Output = stdout;
 }
                                                                        /*}}}*/
@@ -735,7 +766,7 @@ bool ContentsWriter::ReadFromPkgs(string PkgFile,string PkgCompress)
    
    // Open the package file
    int CompFd = -1;
-   int Proc = -1;
+   pid_t Proc = -1;
    if (Pkgs.OpenOld(CompFd,Proc) == false)
       return false;
    
@@ -776,4 +807,125 @@ bool ContentsWriter::ReadFromPkgs(string PkgFile,string PkgCompress)
    
    return true;
 }
+
                                                                        /*}}}*/
+
+// ReleaseWriter::ReleaseWriter - Constructor                          /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+ReleaseWriter::ReleaseWriter(string DB)
+{
+   AddPattern("Packages");
+   AddPattern("Packages.gz");
+   AddPattern("Packages.bz2");
+   AddPattern("Sources");
+   AddPattern("Sources.gz");
+   AddPattern("Sources.bz2");
+   AddPattern("Release");
+   AddPattern("md5sum.txt");
+
+   Output = stdout;
+   time_t now = time(NULL);
+   char datestr[128];
+   if (strftime(datestr, sizeof(datestr), "%a, %d %b %Y %H:%M:%S UTC",
+                gmtime(&now)) == 0)
+   {
+      datestr[0] = '\0';
+   }
+
+   map<string,string> Fields;
+   Fields["Origin"] = "";
+   Fields["Label"] = "";
+   Fields["Suite"] = "";
+   Fields["Version"] = "";
+   Fields["Codename"] = "";
+   Fields["Date"] = datestr;
+   Fields["Architectures"] = "";
+   Fields["Components"] = "";
+   Fields["Description"] = "";
+
+   for(map<string,string>::const_iterator I = Fields.begin();
+       I != Fields.end();
+       ++I)
+   {
+      string Config = string("APT::FTPArchive::Release::") + (*I).first;
+      string Value = _config->Find(Config, (*I).second.c_str());
+      if (Value == "")
+         continue;
+
+      fprintf(Output, "%s: %s\n", (*I).first.c_str(), Value.c_str());
+   }
+}
+                                                                       /*}}}*/
+// ReleaseWriter::DoPackage - Process a single package                 /*{{{*/
+// ---------------------------------------------------------------------
+bool ReleaseWriter::DoPackage(string FileName)
+{
+   // Strip the DirStrip prefix from the FileName and add the PathPrefix
+   string NewFileName;
+   if (DirStrip.empty() == false &&
+       FileName.length() > DirStrip.length() &&
+       stringcmp(FileName.begin(),FileName.begin() + DirStrip.length(),
+                DirStrip.begin(),DirStrip.end()) == 0)
+   {
+      NewFileName = string(FileName.begin() + DirStrip.length(),FileName.end());
+      while (NewFileName[0] == '/')
+         NewFileName = string(NewFileName.begin() + 1,NewFileName.end());
+   }
+   else 
+      NewFileName = FileName;
+
+   if (PathPrefix.empty() == false)
+      NewFileName = flCombine(PathPrefix,NewFileName);
+
+   FileFd fd(FileName, FileFd::ReadOnly);
+
+   if (!fd.IsOpen())
+   {
+      return false;
+   }
+
+   CheckSums[NewFileName].size = fd.Size();
+
+   MD5Summation MD5;
+   MD5.AddFD(fd.Fd(), fd.Size());
+   CheckSums[NewFileName].MD5 = MD5.Result();
+
+   fd.Seek(0);
+   SHA1Summation SHA1;
+   SHA1.AddFD(fd.Fd(), fd.Size());
+   CheckSums[NewFileName].SHA1 = SHA1.Result();
+
+   fd.Close();
+   
+   return true;
+}
+
+                                                                       /*}}}*/
+// ReleaseWriter::Finish - Output the checksums                                /*{{{*/
+// ---------------------------------------------------------------------
+void ReleaseWriter::Finish()
+{
+   fprintf(Output, "MD5Sum:\n");
+   for(map<string,struct CheckSum>::iterator I = CheckSums.begin();
+       I != CheckSums.end();
+       ++I)
+   {
+      fprintf(Output, " %s %16ld %s\n",
+              (*I).second.MD5.c_str(),
+              (*I).second.size,
+              (*I).first.c_str());
+   }
+
+   fprintf(Output, "SHA1:\n");
+   for(map<string,struct CheckSum>::iterator I = CheckSums.begin();
+       I != CheckSums.end();
+       ++I)
+   {
+      fprintf(Output, " %s %16ld %s\n",
+              (*I).second.SHA1.c_str(),
+              (*I).second.size,
+              (*I).first.c_str());
+   }
+}
+