]> git.saurik.com Git - apt.git/blobdiff - ftparchive/apt-ftparchive.cc
Do not buffer writes larger than the buffer if possible
[apt.git] / ftparchive / apt-ftparchive.cc
index cf667483c6494b4852832bddc45966e39c758be2..d985646f7ae7e7efb0144a2b2c64bc494dbf7e22 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <apt-private/private-cmndline.h>
 #include <apt-private/private-output.h>
+#include <apt-private/private-main.h>
 
 #include <algorithm>
 #include <climits>
@@ -67,6 +68,7 @@ struct PackageMap
 
    // We generate for this given arch
    string Arch;
+   bool IncludeArchAll;
    
    // Stuff for the Source File
    string SrcFile;
@@ -121,9 +123,9 @@ struct PackageMap
                    vector<PackageMap>::iterator End,
                    unsigned long &Left);
    
-   PackageMap() : LongDesc(true), TransWriter(NULL), DeLinkLimit(0), Permissions(1),
-                 ContentsDone(false), PkgDone(false), SrcDone(false),
-                 ContentsMTime(0) {};
+   PackageMap() : IncludeArchAll(true), LongDesc(true), TransWriter(NULL),
+                 DeLinkLimit(0), Permissions(1), ContentsDone(false),
+                 PkgDone(false), SrcDone(false), ContentsMTime(0) {};
 };
                                                                        /*}}}*/
 
@@ -135,7 +137,7 @@ void PackageMap::GetGeneral(Configuration &Setup,Configuration &Block)
    PathPrefix = Block.Find("PathPrefix");
    
    if (Block.FindB("External-Links",true) == false)
-      DeLinkLimit = Setup.FindI("Default::DeLinkLimit",UINT_MAX);
+      DeLinkLimit = Setup.FindI("Default::DeLinkLimit", std::numeric_limits<unsigned int>::max());
    else
       DeLinkLimit = 0;
    
@@ -183,7 +185,7 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats)
    PackagesWriter Packages(&Comp.Input, TransWriter, flCombine(CacheDir,BinCacheDB),
                           flCombine(OverrideDir,BinOverride),
                           flCombine(OverrideDir,ExtraOverride),
-                          Arch);
+                          Arch, IncludeArchAll);
    if (PkgExt.empty() == false && Packages.SetExts(PkgExt) == false)
       return _error->Error(_("Package extension list is too long"));
    if (_error->PendingError() == true)
@@ -363,7 +365,7 @@ bool PackageMap::GenContents(Configuration &Setup,
    MultiCompress Comp(flCombine(ArchiveDir,this->Contents),
                      CntCompress,Permissions);
    Comp.UpdateMTime = Setup.FindI("Default::ContentsAge",10)*24*60*60;
-   ContentsWriter Contents(&Comp.Input, "", Arch);
+   ContentsWriter Contents(&Comp.Input, "", Arch, IncludeArchAll);
    if (PkgExt.empty() == false && Contents.SetExts(PkgExt) == false)
       return _error->Error(_("Package extension list is too long"));
    if (_error->PendingError() == true)
@@ -486,6 +488,8 @@ static void LoadTree(vector<PackageMap> &PkgList, std::vector<TranslationWriter*
    bool const LongDescription = Setup.FindB("Default::LongDescription",
                                        _config->FindB("APT::FTPArchive::LongDescription", true));
    string const TranslationCompress = Setup.Find("Default::Translation::Compress",". gzip").c_str();
+   bool const ConfIncludeArchAllExists = _config->Exists("APT::FTPArchive::IncludeArchitectureAll");
+   bool const ConfIncludeArchAll = _config->FindB("APT::FTPArchive::IncludeArchitectureAll", true);
 
    // Process 'tree' type sections
    const Configuration::Item *Top = Setup.Tree("tree");
@@ -500,25 +504,32 @@ static void LoadTree(vector<PackageMap> &PkgList, std::vector<TranslationWriter*
       string Section;
       while (ParseQuoteWord(Sections,Section) == true)
       {
-        string Arch;
-        struct SubstVar const Vars[] = {{"$(DIST)",&Dist},
+        struct SubstVar Vars[] = {{"$(DIST)",&Dist},
                                         {"$(SECTION)",&Section},
-                                        {"$(ARCH)",&Arch},
-                                        {NULL, NULL}};
+                                        {"$(ARCH)",nullptr},
+                                        {nullptr, nullptr}};
         mode_t const Perms = Block.FindI("FileMode", Permissions);
         bool const LongDesc = Block.FindB("LongDescription", LongDescription);
-        TranslationWriter *TransWriter = NULL;
-
-        string const Tmp2 = Block.Find("Architectures");
-        const char *Archs = Tmp2.c_str();
-        while (ParseQuoteWord(Archs,Arch) == true)
+        TranslationWriter *TransWriter = nullptr;
+
+        std::string Tmp2 = Block.Find("Architectures");
+        std::transform(Tmp2.begin(), Tmp2.end(), Tmp2.begin(), ::tolower);
+        std::vector<std::string> const Archs = VectorizeString(Tmp2, ' ');
+        bool IncludeArchAll;
+        if (ConfIncludeArchAllExists == true)
+           IncludeArchAll = ConfIncludeArchAll;
+        else
+           IncludeArchAll = std::find(Archs.begin(), Archs.end(), "all") == Archs.end();
+        for (auto const& Arch: Archs)
         {
+           if (Arch.empty()) continue;
+           Vars[2].Contents = &Arch;
            PackageMap Itm;
            Itm.Permissions = Perms;
            Itm.BinOverride = SubstVar(Block.Find("BinOverride"),Vars);
            Itm.InternalPrefix = SubstVar(Block.Find("InternalPrefix",DIPrfx.c_str()),Vars);
 
-           if (stringcasecmp(Arch,"source") == 0)
+           if (Arch == "source")
            {
               Itm.SrcOverride = SubstVar(Block.Find("SrcOverride"),Vars);
               Itm.BaseDir = SubstVar(Block.Find("SrcDirectory",DSDir.c_str()),Vars);
@@ -535,6 +546,7 @@ static void LoadTree(vector<PackageMap> &PkgList, std::vector<TranslationWriter*
               Itm.PkgFile = SubstVar(Block.Find("Packages",DPkg.c_str()),Vars);
               Itm.Tag = SubstVar("$(DIST)/$(SECTION)/$(ARCH)",Vars);
               Itm.Arch = Arch;
+              Itm.IncludeArchAll = IncludeArchAll;
               Itm.LongDesc = LongDesc;
               if (TransWriter == NULL && DTrans.empty() == false && LongDesc == false && DTrans != "/dev/null")
               {
@@ -603,16 +615,9 @@ static void LoadBinDir(vector<PackageMap> &PkgList,Configuration &Setup)
 }
                                                                        /*}}}*/
 
-// ShowHelp - Show the help text                                       /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-static bool ShowHelp(CommandLine &)
+static bool ShowHelp(CommandLine &)                                    /*{{{*/
 {
-   ioprintf(cout, "%s %s (%s)\n", PACKAGE, PACKAGE_VERSION, COMMON_ARCH);
-   if (_config->FindB("version") == true)
-      return true;
-
-   cout << 
+   std::cout <<
     _("Usage: apt-ftparchive [options] command\n"
       "Commands: packages binarypath [overridefile [pathprefix]]\n"
       "          sources srcpath [overridefile [pathprefix]]\n"
@@ -651,7 +656,6 @@ static bool ShowHelp(CommandLine &)
       "  --contents  Control contents file generation\n"
       "  -c=?  Read this configuration file\n"
       "  -o=?  Set an arbitrary configuration option") << endl;
-   
    return true;
 }
                                                                        /*}}}*/
@@ -669,7 +673,8 @@ static bool SimpleGenPackages(CommandLine &CmdL)
    
    // Create a package writer object.
    PackagesWriter Packages(NULL, NULL, _config->Find("APT::FTPArchive::DB"),
-                          Override, "", _config->Find("APT::FTPArchive::Architecture"));
+                          Override, "", _config->Find("APT::FTPArchive::Architecture"),
+                          _config->FindB("APT::FTPArchive::IncludeArchitectureAll", true));
    if (_error->PendingError() == true)
       return false;
    
@@ -814,12 +819,12 @@ static bool DoGeneratePackagesAndSources(Configuration &Setup,
       _error->DumpErrors();
       
       // Do the generation for Packages
-      for (End = List; End->Str != 0; End++)
+      for (End = List; End->Str != 0; ++End)
       {
         if (End->Hit == false)
            continue;
         
-        PackageMap *I = (PackageMap *)End->UserData;
+        PackageMap * const I = static_cast<PackageMap *>(End->UserData);
         if (I->PkgDone == true)
            continue;
         if (I->GenPackages(Setup,Stats) == false)
@@ -827,12 +832,12 @@ static bool DoGeneratePackagesAndSources(Configuration &Setup,
       }
       
       // Do the generation for Sources
-      for (End = List; End->Str != 0; End++)
+      for (End = List; End->Str != 0; ++End)
       {
         if (End->Hit == false)
            continue;
         
-        PackageMap *I = (PackageMap *)End->UserData;
+        PackageMap * const I = static_cast<PackageMap *>(End->UserData);
         if (I->SrcDone == true)
            continue;
         if (I->GenSources(Setup,SrcStats) == false)
@@ -871,7 +876,8 @@ static bool DoGenerateContents(Configuration &Setup,
       that describe the debs it indexes. Since the package files contain 
       hashes of the .debs this means they have not changed either so the 
       contents must be up to date. */
-   unsigned long MaxContentsChange = Setup.FindI("Default::MaxContentsChange",UINT_MAX)*1024;
+   unsigned long MaxContentsChange = Setup.FindI("Default::MaxContentsChange",
+                                                 std::numeric_limits<unsigned int>::max())*1024;
    for (vector<PackageMap>::iterator I = PkgList.begin(); I != PkgList.end(); ++I)
    {
       // This record is not relevant
@@ -1023,51 +1029,31 @@ static bool Clean(CommandLine &CmdL)
 }
                                                                        /*}}}*/
 
-int main(int argc, const char *argv[])
+static std::vector<aptDispatchWithHelp> GetCommands()                  /*{{{*/
 {
-   setlocale(LC_ALL, "");
-   CommandLine::Args Args[] = {
-      {'h',"help","help",0},
-      {0,"md5","APT::FTPArchive::MD5",0},
-      {0,"sha1","APT::FTPArchive::SHA1",0},
-      {0,"sha256","APT::FTPArchive::SHA256",0},
-      {'v',"version","version",0},
-      {'d',"db","APT::FTPArchive::DB",CommandLine::HasArg},
-      {'s',"source-override","APT::FTPArchive::SourceOverride",CommandLine::HasArg},
-      {'q',"quiet","quiet",CommandLine::IntLevel},
-      {'q',"silent","quiet",CommandLine::IntLevel},
-      {0,"delink","APT::FTPArchive::DeLinkAct",0},
-      {0,"readonly","APT::FTPArchive::ReadOnlyDB",0},
-      {0,"contents","APT::FTPArchive::Contents",0},
-      {'a',"arch","APT::FTPArchive::Architecture",CommandLine::HasArg},
-      {'c',"config-file",0,CommandLine::ConfigFile},
-      {'o',"option",0,CommandLine::ArbItem},
-      {0,0,0,0}};
-   CommandLine::Dispatch Cmds[] = {{"packages",&SimpleGenPackages},
-                                   {"contents",&SimpleGenContents},
-                                   {"sources",&SimpleGenSources},
-                                   {"release",&SimpleGenRelease},
-                                   {"generate",&Generate},
-                                   {"clean",&Clean},
-                                  {"help",&ShowHelp},
-                                   {0,0}};
+   return {
+      {"packages",&SimpleGenPackages, nullptr},
+      {"contents",&SimpleGenContents, nullptr},
+      {"sources",&SimpleGenSources, nullptr},
+      {"release",&SimpleGenRelease, nullptr},
+      {"generate",&Generate, nullptr},
+      {"clean",&Clean, nullptr},
+      {nullptr, nullptr, nullptr}
+   };
+}
+                                                                       /*}}}*/
+int main(int argc, const char *argv[])                                 /*{{{*/
+{
+   InitLocale();
 
    // Parse the command line and initialize the package library
-   CommandLine CmdL(Args,_config);
-   ParseCommandLine(CmdL, Cmds, Args, &_config, NULL, argc, argv, ShowHelp);
+   CommandLine CmdL;
+   auto const Cmds = ParseCommandLine(CmdL, APT_CMD::APT_FTPARCHIVE, &_config, NULL, argc, argv, ShowHelp, &GetCommands);
 
    _config->CndSet("quiet",0);
    Quiet = _config->FindI("quiet",0);
    InitOutput(clog.rdbuf());
 
-   // Match the operation
-   CmdL.DispatchArg(Cmds);
-   
-   if (_error->empty() == false)
-   {
-      bool Errors = _error->PendingError();
-      _error->DumpErrors();
-      return Errors == true?100:0;
-   }
-   return 0;
+   return DispatchCommandLine(CmdL, Cmds);
 }
+                                                                       /*}}}*/